libctf: minor error-handling fixes

A transient bug in the preceding change (fixed before commit) exposed a
new failure, of ld/testsuite/ld-ctf/diag-parname.d.  This attempts to
ensure that if we link a dict with child type IDs but no attached
parent, we get a suitable ECTF_NOPARENT error.  This was happening
before this commit, but only by chance, because ctf_variable_iter and
ctf_variable_next check to see if the dict they're passed is a child
dict without an associated parent.  We forgot error-checking on the
ctf_variable_next call, and as a result this was concealed -- and
looking for the problem exposed a new bug.

If any of the lookups beneath ctf_dedup_hash_type fail, the CTF link
does *not* fail, but acts quite bizarrely, skipping the type but
emitting an error to the CTF error/warning log -- so the linker will
report an error, emit a partial CTF dict missing some types, and exit
with exitcode 0 as if nothing went wrong.  Since ctf_dedup_hash_type is
never expected to fail in normal operation, this is surely wrong:
failures at emission time do not emit partial CTF dicts, so failures
at hashing time should not either.

So propagate the error back up.

Also fix a couple of smaller bugs where we fail to properly free things
and/or propagate error codes on various rare link-time errors and
out-of-memory conditions.

libctf/ChangeLog
2021-03-02  Nick Alcock  <nick.alcock@oracle.com>

	* ctf-dedup.c (ctf_dedup): Pass on errors from ctf_dedup_hash_type.
	Call ctf_dedup_fini properly on other errors.
	(ctf_dedup_emit_type): Set the errno on dynhash insertion failure.
	* ctf-link.c (ctf_link_deduplicating_per_cu): Close outputs beyond
	output 0 when asserting because >1 output is found.
	(ctf_link_deduplicating): Likewise, when asserting because the
	shared output is not the same as the passed-in fp.
This commit is contained in:
Nick Alcock 2021-03-02 15:10:05 +00:00
parent f5060e5633
commit 4659554b28
3 changed files with 32 additions and 8 deletions

View file

@ -1924,15 +1924,17 @@ ctf_dedup (ctf_dict_t *output, ctf_dict_t **inputs, uint32_t ninputs,
while ((id = ctf_type_next (inputs[i], &it, NULL, 1)) != CTF_ERR)
{
ctf_dedup_hash_type (output, inputs[i], inputs, parents,
i, id, 0, 0, ctf_dedup_populate_mappings);
if (ctf_dedup_hash_type (output, inputs[i], inputs,
parents, i, id, 0, 0,
ctf_dedup_populate_mappings) == NULL)
goto err; /* errno is set for us. */
}
if (ctf_errno (inputs[i]) != ECTF_NEXT_END)
{
ctf_set_errno (output, ctf_errno (inputs[i]));
ctf_err_warn (output, 0, 0, _("iteration failure "
"computing type hashes"));
return -1;
goto err;
}
}
@ -1943,7 +1945,7 @@ ctf_dedup (ctf_dict_t *output, ctf_dict_t **inputs, uint32_t ninputs,
ctf_dprintf ("Detecting type name ambiguity\n");
if (ctf_dedup_detect_name_ambiguity (output, inputs) < 0)
return -1; /* errno is set for us. */
goto err; /* errno is set for us. */
/* If the link mode is CTF_LINK_SHARE_DUPLICATED, we change any unconflicting
types whose output mapping references only one input dict into a
@ -1953,7 +1955,7 @@ ctf_dedup (ctf_dict_t *output, ctf_dict_t **inputs, uint32_t ninputs,
{
ctf_dprintf ("Conflictifying unshared types\n");
if (ctf_dedup_conflictify_unshared (output, inputs) < 0)
return -1; /* errno is set for us. */
goto err; /* errno is set for us. */
}
return 0;
@ -2882,7 +2884,10 @@ ctf_dedup_emit_type (const char *hval, ctf_dict_t *output, ctf_dict_t **inputs,
id, out_id);
/* Record the need to emit the members of this structure later. */
if (ctf_dynhash_insert (d->cd_emission_struct_members, id, out_id) < 0)
goto err_target;
{
ctf_set_errno (target, errno);
goto err_target;
}
break;
}
default: