From: Nick Alcock Date: Sun, 16 Feb 2025 19:41:08 +0000 (+0000) Subject: libctf: don't call ctf_type_to_index with types in other dicts X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3737d9200d35d621fc1e4d2a94685f435ae0cb11;p=thirdparty%2Fbinutils-gdb.git libctf: don't call ctf_type_to_index with types in other dicts ctf_type_to_index has never given meaningful results when called with dicts in which the specified type does not reside: its only purpose is to return the offset in various dict-internal arrays in which this type is located, so doing so makes no sense. Stop ctf_lookup_by_name and refresh_pptrtab (which it calls) from doing so. As part of this, refactor ctf_lookup_by_name so that it's a bit less repetitive and squirrelly. --- diff --git a/libctf/ctf-lookup.c b/libctf/ctf-lookup.c index 6ee717a77d7..da3e949962e 100644 --- a/libctf/ctf-lookup.c +++ b/libctf/ctf-lookup.c @@ -47,6 +47,7 @@ static int refresh_pptrtab (ctf_dict_t *fp, ctf_dict_t *pfp) { uint32_t i; + for (i = fp->ctf_pptrtab_typemax; i <= fp->ctf_typemax; i++) { ctf_id_t type = ctf_index_to_type (fp, i); @@ -59,7 +60,7 @@ refresh_pptrtab (ctf_dict_t *fp, ctf_dict_t *pfp) if (ctf_type_isparent (fp, reffed_type)) { - uint32_t idx = ctf_type_to_index (fp, reffed_type); + uint32_t idx = ctf_type_to_index (pfp, reffed_type); /* Guard against references to invalid types. No need to consider the CTF dict corrupt in this case: this pointer just can't be a @@ -122,6 +123,63 @@ isqualifier (const char *s, size_t len) strncmp (qp->q_name, s, qp->q_len) == 0); } +/* Find a pointer to type by looking in the's ctf_pptrtab (if child is set) and + fp->ctf_ptrtab. Return -1 / ECTF_NOTYPE if no type exists. + + Skip lookups if this is a child type and we are looking in the parent (with + child set), because you cannot have a pointer in the parent to a type in the + child (an earlier loop checks for pointers to child types). + + There is extra complexity here because uninitialized elements in the pptrtab + and ptrtab are set to zero, but zero (as the type ID meaning the + unimplemented type) is a valid return type from ctf_lookup_by_name. + (Pointers to types are never of type 0, so this is unambiguous, just fiddly + to deal with.) */ + +static ctf_id_t +lookup_ptrtab (ctf_dict_t *fp, ctf_dict_t *child, ctf_id_t type, int *in_child) +{ + ctf_id_t ntype = 0; + uint32_t idx; + + *in_child = 0; + + /* If we're looking up types in the parent from the perspective of a child, + don't even try looking if this is a child type: this is done earlier. */ + + if (child && ctf_type_ischild (fp, type)) + return ctf_set_typed_errno (fp, ECTF_NOTYPE); + + idx = ctf_type_to_index (fp, type); + ntype = CTF_ERR; + + /* Lookup of parent type in child: check pptrtab. */ + if (child) + { + if (idx < child->ctf_pptrtab_len) + { + ntype = child->ctf_pptrtab[idx]; + if (ntype) + *in_child = 1; + else + ntype = CTF_ERR; + } + } + /* Type, and pointer to it, might still be in the parent: check its ptrtab. */ + if (ntype == CTF_ERR) + { + idx = ctf_type_to_index (fp, type); + ntype = fp->ctf_ptrtab[idx]; + + if (ntype == 0) + ntype = CTF_ERR; + } + if (ntype == CTF_ERR) + return ctf_set_typed_errno (fp, ECTF_NOTYPE); + + return ntype; +} + /* Attempt to convert the given C type name into the corresponding CTF type ID. It is not possible to do complete and proper conversion of type names without implementing a more full-fledged parser, which is necessary to @@ -164,65 +222,51 @@ ctf_lookup_by_name_internal (ctf_dict_t *fp, ctf_dict_t *child, from resolving the type down to its base type and use that instead. This helps with cases where the CTF data includes "struct foo *" but not "foo_t *" and the user tries to access "foo_t *" in the - debugger. - - There is extra complexity here because uninitialized elements in - the pptrtab and ptrtab are set to zero, but zero (as the type ID - meaning the unimplemented type) is a valid return type from - ctf_lookup_by_name. (Pointers to types are never of type 0, so - this is unambiguous, just fiddly to deal with.) */ + debugger. */ - uint32_t idx = ctf_type_to_index (fp, type); int in_child = 0; - ntype = CTF_ERR; - if (child && idx < child->ctf_pptrtab_len) - { - ntype = child->ctf_pptrtab[idx]; - if (ntype) - in_child = 1; - else - ntype = CTF_ERR; - } + /* Parent type, not looking in the parent yet? Do so. */ - if (ntype == CTF_ERR) - { - ntype = fp->ctf_ptrtab[idx]; - if (ntype == 0) - ntype = CTF_ERR; - } + if (!child && fp->ctf_flags & LCTF_CHILD + && ctf_type_isparent (fp, type)) + goto notype; + + ntype = lookup_ptrtab (fp, child, type, &in_child); /* Try resolving to its base type and check again. */ - if (ntype == CTF_ERR) + if (ntype == CTF_ERR && ctf_errno (fp) == ECTF_NOTYPE) { + int err; + if (child) - ntype = ctf_type_resolve_unsliced (child, type); + { + ntype = ctf_type_resolve_unsliced (child, type); + err = ctf_errno (child); + } else - ntype = ctf_type_resolve_unsliced (fp, type); - - if (ntype == CTF_ERR) - goto notype; - - idx = ctf_type_to_index (fp, ntype); - - ntype = CTF_ERR; - if (child && idx < child->ctf_pptrtab_len) { - ntype = child->ctf_pptrtab[idx]; - if (ntype) - in_child = 1; - else - ntype = CTF_ERR; + ntype = ctf_type_resolve_unsliced (fp, type); + err = ctf_errno (fp); } if (ntype == CTF_ERR) { - ntype = fp->ctf_ptrtab[idx]; - if (ntype == 0) - ntype = CTF_ERR; + if (err == ECTF_BADID) + goto notype; + else + return ctf_set_typed_errno (fp, err); } - if (ntype == CTF_ERR) + + ntype = lookup_ptrtab (fp, child, type, &in_child); + } + if (ntype == CTF_ERR) + { + if (ctf_errno (fp) == ECTF_BADID + || ctf_errno (fp) == ECTF_NOTYPE) goto notype; + else + return -1; /* errno is set for us. */ } if (in_child)