aboutsummaryrefslogtreecommitdiff
path: root/libctf/ctf-types.c
diff options
context:
space:
mode:
authorNick Alcock <nick.alcock@oracle.com>2023-04-05 17:21:32 +0100
committerNick Alcock <nick.alcock@oracle.com>2023-04-08 16:07:17 +0100
commitd7474051e87c5804c2b674c0d3ad78030f0464a7 (patch)
tree26e0e288d9f536d62807077854efa77a8538cdd6 /libctf/ctf-types.c
parent30a794e9f1db2de9099ed4c494d917d4e86de0fd (diff)
downloadgdb-d7474051e87c5804c2b674c0d3ad78030f0464a7.zip
gdb-d7474051e87c5804c2b674c0d3ad78030f0464a7.tar.gz
gdb-d7474051e87c5804c2b674c0d3ad78030f0464a7.tar.bz2
libctf: propagate errors from parents correctly
CTF dicts have per-dict errno values: as with other errno values these are set on error and left unchanged on success. This means that all errors *must* set the CTF errno: if a call leaves it unchanged, the caller is apt to find a previous, lingering error and misinterpret it as the real error. There are many places in libctf where we carry out operations on parent dicts as a result of carrying out other user-requested operations on child dicts (e.g. looking up information on a pointer to a type will look up the type as well: the pointer might well be in a child and the type it's a pointer to in the parent). Those operations on the parent might fail; if they do, the error must be correctly reflected on the child that the user-visible operation was carried out on. In many places this was not happening. So, audit and fix all those places. Add tests for as many of those cases as possible so they don't regress. libctf/ * ctf-create.c (ctf_add_slice): Use the original dict. * ctf-lookup.c (ctf_lookup_variable): Propagate errors. (ctf_lookup_symbol_idx): Likewise. * ctf-types.c (ctf_member_next): Likewise. (ctf_type_resolve_unsliced): Likewise. (ctf_type_aname): Likewise. (ctf_member_info): Likewise. (ctf_type_rvisit): Likewise. (ctf_func_type_info): Set the error on the right dict. (ctf_type_encoding): Use the original dict. * testsuite/libctf-writable/error-propagation.*: New test.
Diffstat (limited to 'libctf/ctf-types.c')
-rw-r--r--libctf/ctf-types.c29
1 files changed, 20 insertions, 9 deletions
diff --git a/libctf/ctf-types.c b/libctf/ctf-types.c
index dd82053..c20ff82 100644
--- a/libctf/ctf-types.c
+++ b/libctf/ctf-types.c
@@ -177,7 +177,7 @@ ctf_member_next (ctf_dict_t *fp, ctf_id_t type, ctf_next_t **it,
if (ctf_struct_member (fp, &memb, i->ctn_tp, i->u.ctn_vlen, i->ctn_size,
i->ctn_n) < 0)
- return -1; /* errno is set for us. */
+ return (ctf_set_errno (ofp, ctf_errno (fp)));
membname = ctf_strptr (fp, memb.ctlm_name);
@@ -216,11 +216,12 @@ ctf_member_next (ctf_dict_t *fp, ctf_id_t type, ctf_next_t **it,
ctf_next_destroy (i);
*it = NULL;
i->ctn_type = 0;
- return ret; /* errno is set for us. */
+ ctf_set_errno (ofp, ctf_errno (fp));
+ return ret;
}
if (!ctf_assert (fp, (i->ctn_next == NULL)))
- return -1; /* errno is set for us. */
+ return (ctf_set_errno (ofp, ctf_errno (fp)));
i->ctn_type = 0;
/* This sub-struct has ended: on to the next real member. */
@@ -597,6 +598,7 @@ ctf_type_resolve (ctf_dict_t *fp, ctf_id_t type)
ctf_id_t
ctf_type_resolve_unsliced (ctf_dict_t *fp, ctf_id_t type)
{
+ ctf_dict_t *ofp = fp;
const ctf_type_t *tp;
if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
@@ -606,7 +608,13 @@ ctf_type_resolve_unsliced (ctf_dict_t *fp, ctf_id_t type)
return CTF_ERR; /* errno is set for us. */
if ((LCTF_INFO_KIND (fp, tp->ctt_info)) == CTF_K_SLICE)
- return ctf_type_reference (fp, type);
+ {
+ ctf_id_t ret;
+
+ if ((ret = ctf_type_reference (fp, type)) == CTF_ERR)
+ return (ctf_set_errno (ofp, ctf_errno (fp)));
+ return ret;
+ }
return type;
}
@@ -767,6 +775,7 @@ ctf_type_aname (ctf_dict_t *fp, ctf_id_t type)
break;
err:
+ ctf_set_errno (fp, ctf_errno (rfp));
free (argv);
ctf_decl_fini (&cd);
return NULL;
@@ -1216,8 +1225,8 @@ ctf_type_encoding (ctf_dict_t *fp, ctf_id_t type, ctf_encoding_t *ep)
ctf_id_t underlying;
slice = (ctf_slice_t *) vlen;
- underlying = ctf_type_resolve (fp, slice->cts_type);
- if (ctf_type_encoding (fp, underlying, &underlying_en) < 0)
+ underlying = ctf_type_resolve (ofp, slice->cts_type);
+ if (ctf_type_encoding (ofp, underlying, &underlying_en) < 0)
return -1; /* errno is set for us. */
ep->cte_format = underlying_en.cte_format;
@@ -1409,7 +1418,7 @@ ctf_member_info (ctf_dict_t *fp, ctf_id_t type, const char *name,
const char *membname;
if (ctf_struct_member (fp, &memb, tp, vlen, vbytes, i) < 0)
- return -1; /* errno is set for us. */
+ return (ctf_set_errno (ofp, ctf_errno (fp)));
membname = ctf_strptr (fp, memb.ctlm_name);
@@ -1558,6 +1567,7 @@ ctf_enum_value (ctf_dict_t *fp, ctf_id_t type, const char *name, int *valp)
int
ctf_func_type_info (ctf_dict_t *fp, ctf_id_t type, ctf_funcinfo_t *fip)
{
+ ctf_dict_t *ofp = fp;
const ctf_type_t *tp;
uint32_t kind;
const uint32_t *args;
@@ -1574,7 +1584,7 @@ ctf_func_type_info (ctf_dict_t *fp, ctf_id_t type, ctf_funcinfo_t *fip)
kind = LCTF_INFO_KIND (fp, tp->ctt_info);
if (kind != CTF_K_FUNCTION)
- return (ctf_set_errno (fp, ECTF_NOTFUNC));
+ return (ctf_set_errno (ofp, ECTF_NOTFUNC));
fip->ctc_return = tp->ctt_type;
fip->ctc_flags = 0;
@@ -1638,6 +1648,7 @@ static int
ctf_type_rvisit (ctf_dict_t *fp, ctf_id_t type, ctf_visit_f *func,
void *arg, const char *name, unsigned long offset, int depth)
{
+ ctf_dict_t *ofp = fp;
ctf_id_t otype = type;
const ctf_type_t *tp;
const ctf_dtdef_t *dtd;
@@ -1686,7 +1697,7 @@ ctf_type_rvisit (ctf_dict_t *fp, ctf_id_t type, ctf_visit_f *func,
ctf_lmember_t memb;
if (ctf_struct_member (fp, &memb, tp, vlen, vbytes, i) < 0)
- return -1; /* errno is set for us. */
+ return (ctf_set_errno (ofp, ctf_errno (fp)));
if ((rc = ctf_type_rvisit (fp, memb.ctlm_type,
func, arg, ctf_strptr (fp, memb.ctlm_name),