forked from Imagelibrary/binutils-gdb
libctf, archive, link: fix parent importing
We are about to move to a regime where there are very few things you can do
with most dicts before you ctf_import them. So emit a warning if
ctf_archive_next()'s convenience ctf_import of parents fails. Rip out the
buggy code in ctf_link_deduplicating_open_inputs which opened the parent by
hand (with a hardwired name), and instead rely on ctf_archive_next to do it
for us (which also means we don't end up opening it twice, once in
ctf_archive_next, once in ctf_link_deduplicating_open_inputs).
While we're there, arrange to close the inputs we already opened if opening
of some inputs fails, rather than leaking them. (There are still some leaks
here, so add a comment to remind us to clean them up later.)
libctf/
* ctf-archive.c (ctf_arc_import_parent): Emit a warning if importing
fails.
* ctf-link.c (ctf_link_deduplicating_open_inputs): Rely on the
ctf_archive_next to open parent dicts.
This commit is contained in:
@@ -769,7 +769,10 @@ ctf_arc_import_parent (const ctf_archive_t *arc, ctf_dict_t *fp, int *errp)
|
|||||||
|
|
||||||
if (parent)
|
if (parent)
|
||||||
{
|
{
|
||||||
ctf_import (fp, parent);
|
if (ctf_import (fp, parent) < 0)
|
||||||
|
ctf_err_warn (NULL, 1, ctf_errno (fp),
|
||||||
|
"ctf_arc_import_parent: cannot import: %s",
|
||||||
|
ctf_errmsg (ctf_errno (fp)));
|
||||||
ctf_dict_close (parent);
|
ctf_dict_close (parent);
|
||||||
}
|
}
|
||||||
else if (err != ECTF_ARNNAME)
|
else if (err != ECTF_ARNNAME)
|
||||||
|
|||||||
@@ -711,6 +711,10 @@ ctf_link_deduplicating_count_inputs (ctf_dict_t *fp, ctf_dynhash_t *cu_names,
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ctf_link_deduplicating_close_inputs (ctf_dict_t *fp, ctf_dynhash_t *cu_names,
|
||||||
|
ctf_dict_t **inputs, ssize_t ninputs);
|
||||||
|
|
||||||
/* Allocate and populate an inputs array big enough for a given set of inputs:
|
/* Allocate and populate an inputs array big enough for a given set of inputs:
|
||||||
either a specific set of CU names (those from that set found in the
|
either a specific set of CU names (those from that set found in the
|
||||||
ctf_link_inputs), or the entire ctf_link_inputs (if cu_names is not set).
|
ctf_link_inputs), or the entire ctf_link_inputs (if cu_names is not set).
|
||||||
@@ -763,9 +767,10 @@ ctf_link_deduplicating_open_inputs (ctf_dict_t *fp, ctf_dynhash_t *cu_names,
|
|||||||
const char *one_name = (const char *) name;
|
const char *one_name = (const char *) name;
|
||||||
ctf_link_input_t *one_input;
|
ctf_link_input_t *one_input;
|
||||||
ctf_dict_t *one_fp;
|
ctf_dict_t *one_fp;
|
||||||
ctf_dict_t *parent_fp = NULL;
|
|
||||||
uint32_t parent_i = 0;
|
|
||||||
ctf_next_t *j = NULL;
|
ctf_next_t *j = NULL;
|
||||||
|
ssize_t parent_i;
|
||||||
|
int parent_set = 0;
|
||||||
|
ctf_dict_t *parent_fp = NULL;
|
||||||
|
|
||||||
/* If we are processing CU names, get the real input. All the inputs
|
/* If we are processing CU names, get the real input. All the inputs
|
||||||
will have been opened, if they contained any CTF at all. */
|
will have been opened, if they contained any CTF at all. */
|
||||||
@@ -777,7 +782,7 @@ ctf_link_deduplicating_open_inputs (ctf_dict_t *fp, ctf_dynhash_t *cu_names,
|
|||||||
if (!one_input || (!one_input->clin_arc && !one_input->clin_fp))
|
if (!one_input || (!one_input->clin_arc && !one_input->clin_fp))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Short-circuit: if clin_fp is set, just use it. */
|
/* Short-circuit: if clin_fp is set, just use it. */
|
||||||
if (one_input->clin_fp)
|
if (one_input->clin_fp)
|
||||||
{
|
{
|
||||||
parents_[walk - dedup_inputs] = walk - dedup_inputs;
|
parents_[walk - dedup_inputs] = walk - dedup_inputs;
|
||||||
@@ -786,48 +791,73 @@ ctf_link_deduplicating_open_inputs (ctf_dict_t *fp, ctf_dynhash_t *cu_names,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get and insert the parent archive (if any), if this archive has
|
if (one_input->clin_filename)
|
||||||
multiple members. We assume, as elsewhere, that the parent is named
|
ctf_dprintf ("Opening %s\n", one_input->clin_filename);
|
||||||
_CTF_SECTION. */
|
|
||||||
|
|
||||||
if ((parent_fp = ctf_dict_open (one_input->clin_arc, _CTF_SECTION,
|
/* We disregard the input archive name: either it is the parent (which we can get
|
||||||
&err)) == NULL)
|
via ctf_parent_dict), or we want to put everything into one TU sharing the
|
||||||
|
cuname anyway (if this is a CU-mapped link), or this is the final phase of a
|
||||||
|
relink with CU-mapping off (i.e. ld -r) in which case the cuname is correctly
|
||||||
|
set regardless. */
|
||||||
|
|
||||||
|
while ((one_fp = ctf_archive_next (one_input->clin_arc, &j, NULL,
|
||||||
|
0, &err)) != NULL)
|
||||||
{
|
{
|
||||||
if (err != ECTF_NOMEMBNAM)
|
/* ctf_archive_next either auto-imports the parent, or this *is* the parent.
|
||||||
|
In both cases, we can set the parent up if it's not already set.
|
||||||
|
|
||||||
|
If parent importing failed, we must report an error.
|
||||||
|
|
||||||
|
We must do it first, so we can set later elements of the parents_ array to
|
||||||
|
the parent. */
|
||||||
|
|
||||||
|
if (one_fp->ctf_flags & LCTF_CHILD && one_fp->ctf_parent == NULL)
|
||||||
{
|
{
|
||||||
ctf_next_destroy (i);
|
ctf_next_destroy (i);
|
||||||
ctf_set_errno (fp, err);
|
ctf_set_errno (fp, ECTF_NOPARENT);
|
||||||
|
ctf_err_warn (fp, 0, 0, _("cannot open linker inputs"));
|
||||||
|
goto reported_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parent_set)
|
||||||
|
{
|
||||||
|
if (one_fp->ctf_flags & LCTF_CHILD)
|
||||||
|
parent_fp = one_fp->ctf_parent;
|
||||||
|
else
|
||||||
|
parent_fp = one_fp;
|
||||||
|
|
||||||
|
*walk = parent_fp;
|
||||||
|
parent_i = walk - dedup_inputs;
|
||||||
|
parents_[parent_i] = parent_i;
|
||||||
|
walk++;
|
||||||
|
|
||||||
|
parent_set = 1;
|
||||||
|
|
||||||
|
/* If this is the parent, we don't need to process the child dict itself
|
||||||
|
(because there isn't one). */
|
||||||
|
|
||||||
|
if (!(one_fp->ctf_flags & LCTF_CHILD))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ctf_assert (fp, one_fp->ctf_parent == parent_fp))
|
||||||
|
{
|
||||||
|
ctf_next_destroy (i);
|
||||||
|
goto err; /* errno is set for us. */
|
||||||
|
}
|
||||||
|
|
||||||
|
parents_[walk - dedup_inputs] = parent_i;
|
||||||
|
|
||||||
|
/* This should never happen, but if it *does*, we want to know, because it
|
||||||
|
breaks string lookup and thus eventually everything. */
|
||||||
|
if (one_fp->ctf_flags & LCTF_NO_STR)
|
||||||
|
{
|
||||||
|
ctf_next_destroy (j);
|
||||||
|
ctf_next_destroy (i);
|
||||||
|
ctf_set_errno (fp, ECTF_NOPARENT);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*walk = parent_fp;
|
|
||||||
parent_i = walk - dedup_inputs;
|
|
||||||
walk++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We disregard the input archive name: either it is the parent (which we
|
|
||||||
already have), or we want to put everything into one TU sharing the
|
|
||||||
cuname anyway (if this is a CU-mapped link), or this is the final phase
|
|
||||||
of a relink with CU-mapping off (i.e. ld -r) in which case the cuname
|
|
||||||
is correctly set regardless. */
|
|
||||||
while ((one_fp = ctf_archive_next (one_input->clin_arc, &j, NULL,
|
|
||||||
1, &err)) != NULL)
|
|
||||||
{
|
|
||||||
if (one_fp->ctf_flags & LCTF_CHILD)
|
|
||||||
{
|
|
||||||
/* The contents of the parents array for elements not
|
|
||||||
corresponding to children is undefined. If there is no parent
|
|
||||||
(itself a sign of a likely linker bug or corrupt input), we set
|
|
||||||
it to itself. */
|
|
||||||
|
|
||||||
ctf_import (one_fp, parent_fp);
|
|
||||||
if (parent_fp)
|
|
||||||
parents_[walk - dedup_inputs] = parent_i;
|
|
||||||
else
|
|
||||||
parents_[walk - dedup_inputs] = walk - dedup_inputs;
|
|
||||||
}
|
|
||||||
*walk = one_fp;
|
*walk = one_fp;
|
||||||
walk++;
|
walk++;
|
||||||
}
|
}
|
||||||
@@ -851,10 +881,14 @@ ctf_link_deduplicating_open_inputs (ctf_dict_t *fp, ctf_dynhash_t *cu_names,
|
|||||||
ctf_set_errno (fp, err);
|
ctf_set_errno (fp, err);
|
||||||
|
|
||||||
err:
|
err:
|
||||||
free (dedup_inputs);
|
|
||||||
free (parents_);
|
|
||||||
ctf_err_warn (fp, 0, 0, _("error in deduplicating CTF link "
|
ctf_err_warn (fp, 0, 0, _("error in deduplicating CTF link "
|
||||||
"input allocation"));
|
"input allocation"));
|
||||||
|
reported_err:
|
||||||
|
ctf_link_deduplicating_close_inputs (fp, cu_names, dedup_inputs, ninputs);
|
||||||
|
/* UPTODO XXX fix pre-existing leak of the parents on error. */
|
||||||
|
|
||||||
|
free (dedup_inputs);
|
||||||
|
free (parents_);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user