forked from Imagelibrary/binutils-gdb
libctf: open, types: ctf_import for BTF
ctf_import needs a bunch of fixes to work with pure BTF dicts -- and, for that matter, importing newly-created parent dicts that have never been written out, which may have a bunch of nonprovisional types (if types were added to it before any imports were done) or may not (if at least one ctf_import into it was done before any types were added). So we adjust things so that the values that are checked against are the nonprovisional-types values: the header revisions actually changed the name of cth_parent_typemax to cth_parent_ntypes to make this clearer, so catch up with that. In the parent, we have to use ctf_idmax, not ctf_typemax. One thing we must prohibit is that you cannot add a bunch of types to a child and then import a parent into it: the type IDs will all be wrong and the string offsets more so. This was partly prohibited: prohibit it entirely (excepting only that the not-actually-written-out void type we might add to new BTF dicts does not influence this check). Since BTF children don't have a cth_parent_ntypes or a cth_parent_strlen, we cannot check this stuff, but just set them and hope.
This commit is contained in:
@@ -2641,20 +2641,30 @@ ctf_import_internal (ctf_dict_t *fp, ctf_dict_t *pfp, int unreffed)
|
||||
number of types. (Provisional types excepted: they go at the top of the
|
||||
type ID space, and will not overlap any child types.) */
|
||||
|
||||
if (pfp->ctf_idmax != fp->ctf_header->cth_parent_typemax)
|
||||
if (pfp->ctf_idmax != fp->ctf_header->cth_parent_ntypes)
|
||||
{
|
||||
if (fp->ctf_header->cth_parent_typemax != 0)
|
||||
if (fp->ctf_header->cth_parent_ntypes != 0)
|
||||
{
|
||||
ctf_err_warn (fp, 0, ECTF_WRONGPARENT,
|
||||
_("ctf_import: incorrect parent dict: %u types expected, %u found"),
|
||||
fp->ctf_header->cth_parent_typemax, pfp->ctf_idmax);
|
||||
fp->ctf_header->cth_parent_ntypes, pfp->ctf_idmax);
|
||||
return (ctf_set_errno (fp, ECTF_WRONGPARENT));
|
||||
}
|
||||
else if (fp->ctf_header->cth_parent_typemax == 0)
|
||||
else if (fp->ctf_opened_btf)
|
||||
{
|
||||
/* A pure BTF dict does not track the number of types in the parent:
|
||||
just update and hope. */
|
||||
|
||||
fp->ctf_header->cth_parent_ntypes = pfp->ctf_idmax;
|
||||
}
|
||||
else if (fp->ctf_header->cth_parent_ntypes == 0)
|
||||
{
|
||||
/* If we are importing into a parent dict, the child dict had better
|
||||
be empty. Set its starting type ID, which need not be zero: the
|
||||
parent can already have types. */
|
||||
parent can already have types. We assign typemax rather than
|
||||
idmax because when this is a new dict we want the types to count
|
||||
up from the number of types currently in the parent, not the number
|
||||
in the parent when it was opened. */
|
||||
|
||||
if (fp->ctf_typemax != 0)
|
||||
{
|
||||
@@ -2663,17 +2673,23 @@ ctf_import_internal (ctf_dict_t *fp, ctf_dict_t *pfp, int unreffed)
|
||||
fp->ctf_typemax);
|
||||
return (ctf_set_errno (fp, EINVAL));
|
||||
}
|
||||
fp->ctf_header->cth_parent_typemax = pfp->ctf_typemax;
|
||||
fp->ctf_header->cth_parent_ntypes = pfp->ctf_typemax;
|
||||
}
|
||||
}
|
||||
|
||||
/* We might in time be able to lift this restriction, but it is unlikely to be
|
||||
something anyone would want to do, so let's not bother for now. */
|
||||
/* No importing dicts with provisional strings in (except for the void one
|
||||
added to all new dicts). We might in time be able to lift this
|
||||
restriction, but it is unlikely to be something anyone would want to do, so
|
||||
let's not bother for now. If we have a system-created void type, it might
|
||||
have instantiated a new string. */
|
||||
|
||||
if (ctf_dynhash_elements (fp->ctf_prov_strtab) != 0)
|
||||
if ((fp->ctf_void_type == NULL
|
||||
&& ctf_dynhash_elements (fp->ctf_prov_strtab) != 0)
|
||||
|| (fp->ctf_void_type != NULL
|
||||
&& ctf_dynhash_elements (fp->ctf_prov_strtab) > 1))
|
||||
{
|
||||
ctf_err_warn (fp, 0, EINVAL,
|
||||
_("ctf_import: child dict already has %zi bytes of strings, cannot import"),
|
||||
_("ctf_import: child dict already has %zi strings, cannot import"),
|
||||
ctf_dynhash_elements (fp->ctf_prov_strtab));
|
||||
return (ctf_set_errno (fp, EINVAL));
|
||||
}
|
||||
@@ -2694,8 +2710,16 @@ ctf_import_internal (ctf_dict_t *fp, ctf_dict_t *pfp, int unreffed)
|
||||
fp->ctf_parent_unreffed = unreffed;
|
||||
fp->ctf_parent = pfp;
|
||||
|
||||
/* BTF dicts don't have any parent strlen in the header, but we need to know
|
||||
it to dereference strings. */
|
||||
|
||||
if (fp->ctf_opened_btf)
|
||||
fp->ctf_header->cth_parent_strlen = pfp->ctf_str[CTF_STRTAB_0].cts_len;
|
||||
|
||||
/* If this is a dict that hasn't previously allowed string lookups,
|
||||
we can allow them now, and finish initialization. */
|
||||
we can allow them now, and finish initialization. (This requires us to
|
||||
figure out whether the buffer contains pure BTF or not: we can do that by
|
||||
checking the CTF-specific magic number in the header we read in.) */
|
||||
|
||||
fp->ctf_flags |= LCTF_CHILD;
|
||||
fp->ctf_flags &= ~LCTF_NO_STR;
|
||||
|
||||
Reference in New Issue
Block a user