+2020-07-22 Nick Alcock <nick.alcock@oracle.com>
+
+ * ctf-impl.h (ctf_file_t): Improve comments.
+ <ctf_link_cu_mapping>: Split into...
+ <ctf_link_in_cu_mapping>: ... this...
+ <ctf_link_out_cu_mapping>: ... and this.
+ * ctf-create.c (ctf_serialize): Adjust.
+ * ctf-open.c (ctf_file_close): Likewise.
+ * ctf-link.c (ctf_create_per_cu): Look things up in the
+ in_cu_mapping instead of the cu_mapping.
+ (ctf_link_add_cu_mapping): The deduplicating link will define
+ what happens if many FROMs share a TO.
+ (ctf_link_add_cu_mapping): Create in_cu_mapping and
+ out_cu_mapping. Do not create ctf_link_outputs here any more, or
+ create per-CU dicts here: they are already created when needed.
+ (ctf_link_one_variable): Log a debug message if we skip a
+ variable due to its type being concealed in a CU-mapped link.
+ (This is probably too common a case to make into a warning.)
+ (ctf_link): Create empty per-CU dicts if requested.
+
2020-07-22 Nick Alcock <nick.alcock@oracle.com>
* ctf-link.c (ctf_link_write): Close the fd.
ctf_list_t ctf_errs_warnings; /* CTF errors and warnings. */
ctf_dynhash_t *ctf_link_inputs; /* Inputs to this link. */
ctf_dynhash_t *ctf_link_outputs; /* Additional outputs from this link. */
- ctf_dynhash_t *ctf_link_type_mapping; /* Map input types to output types. */
- ctf_dynhash_t *ctf_link_cu_mapping; /* Map CU names to CTF dict names. */
- /* Allow the caller to Change the name of link archive members. */
+
+ /* Map input types to output types: populated in each output dict.
+ Key is a ctf_link_type_key_t: value is a type ID. Used by
+ nondeduplicating links and ad-hoc ctf_add_type calls only. */
+ ctf_dynhash_t *ctf_link_type_mapping;
+
+ /* Map input CU names to output CTF dict names: populated in the top-level
+ output dict.
+
+ Key and value are dynamically-allocated strings. */
+ ctf_dynhash_t *ctf_link_in_cu_mapping;
+
+ /* Map output CTF dict names to input CU names: populated in the top-level
+ output dict. A hash of string to hash (set) of strings. Key and
+ individual value members are shared with ctf_link_in_cu_mapping. */
+ ctf_dynhash_t *ctf_link_out_cu_mapping;
+
/* CTF linker flags. */
int ctf_link_flags;
+ /* Allow the caller to change the name of link archive members. */
ctf_link_memb_name_changer_f *ctf_link_memb_name_changer;
void *ctf_link_memb_name_changer_arg; /* Argument for it. */
ctf_dynhash_t *ctf_add_processing; /* Types ctf_add_type is working on now. */
dictionary name. We prefer the filename because this is easier for likely
callers to determine. */
- if (fp->ctf_link_cu_mapping)
+ if (fp->ctf_link_in_cu_mapping)
{
- if (((ctf_name = ctf_dynhash_lookup (fp->ctf_link_cu_mapping, filename)) == NULL) &&
- ((ctf_name = ctf_dynhash_lookup (fp->ctf_link_cu_mapping, cuname)) == NULL))
+ if (((ctf_name = ctf_dynhash_lookup (fp->ctf_link_in_cu_mapping,
+ filename)) == NULL) &&
+ ((ctf_name = ctf_dynhash_lookup (fp->ctf_link_in_cu_mapping,
+ cuname)) == NULL))
ctf_name = filename;
}
/* Add a mapping directing that the CU named FROM should have its
conflicting/non-duplicate types (depending on link mode) go into a container
- named TO. Many FROMs can share a TO: in this case, the effect on conflicting
- types is not yet defined (but in time an auto-renaming algorithm will be
- added: ugly, but there is really no right thing one can do in this
- situation).
+ named TO. Many FROMs can share a TO.
We forcibly add a container named TO in every case, even though it may well
wind up empty, because clients that use this facility usually expect to find
ctf_link_add_cu_mapping (ctf_file_t *fp, const char *from, const char *to)
{
int err;
- char *f, *t;
+ char *f = NULL, *t = NULL;
+ ctf_dynhash_t *one_out;
+
+ if (fp->ctf_link_in_cu_mapping == NULL)
+ fp->ctf_link_in_cu_mapping = ctf_dynhash_create (ctf_hash_string,
+ ctf_hash_eq_string, free,
+ free);
+ if (fp->ctf_link_in_cu_mapping == NULL)
+ goto oom;
- if (fp->ctf_link_cu_mapping == NULL)
- fp->ctf_link_cu_mapping = ctf_dynhash_create (ctf_hash_string,
- ctf_hash_eq_string, free,
- free);
- if (fp->ctf_link_cu_mapping == NULL)
- return ctf_set_errno (fp, ENOMEM);
+ if (fp->ctf_link_out_cu_mapping == NULL)
+ fp->ctf_link_out_cu_mapping = ctf_dynhash_create (ctf_hash_string,
+ ctf_hash_eq_string, free,
+ (ctf_hash_free_fun)
+ ctf_dynhash_destroy);
+ if (fp->ctf_link_out_cu_mapping == NULL)
+ goto oom;
- if (fp->ctf_link_outputs == NULL)
- fp->ctf_link_outputs = ctf_dynhash_create (ctf_hash_string,
- ctf_hash_eq_string, free,
- (ctf_hash_free_fun)
- ctf_file_close);
+ f = strdup (from);
+ t = strdup (to);
+ if (!f || !t)
+ goto oom;
- if (fp->ctf_link_outputs == NULL)
- return ctf_set_errno (fp, ENOMEM);
+ /* Track both in a list from FROM to TO and in a list from TO to a list of
+ FROM. The former is used to create TUs with the mapped-to name at need:
+ the latter is used in deduplicating links to pull in all input CUs
+ corresponding to a single output CU. */
+
+ if ((err = ctf_dynhash_insert (fp->ctf_link_in_cu_mapping, f, t)) < 0)
+ {
+ ctf_set_errno (fp, err);
+ goto oom_noerrno;
+ }
+ /* f and t are now owned by the in_cu_mapping: reallocate them. */
f = strdup (from);
t = strdup (to);
if (!f || !t)
goto oom;
- if (ctf_create_per_cu (fp, t, t) == NULL)
- goto oom_noerrno; /* Errno is set for us. */
+ if ((one_out = ctf_dynhash_lookup (fp->ctf_link_out_cu_mapping, t)) == NULL)
+ {
+ if ((one_out = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
+ free, NULL)) == NULL)
+ goto oom;
+ if ((err = ctf_dynhash_insert (fp->ctf_link_out_cu_mapping,
+ t, one_out)) < 0)
+ {
+ ctf_dynhash_destroy (one_out);
+ ctf_set_errno (fp, err);
+ goto oom_noerrno;
+ }
+ }
+ else
+ free (t);
- err = ctf_dynhash_insert (fp->ctf_link_cu_mapping, f, t);
- if (err)
+ if (ctf_dynhash_insert (one_out, f, NULL) < 0)
{
ctf_set_errno (fp, err);
goto oom_noerrno;
ctf_link (ctf_file_t *fp, int flags)
{
ctf_link_in_member_cb_arg_t arg;
+ ctf_next_t *i = NULL;
+ int err;
memset (&arg, 0, sizeof (struct ctf_link_in_member_cb_arg));
arg.out_fp = fp;
if (fp->ctf_link_outputs == NULL)
return ctf_set_errno (fp, ENOMEM);
+ /* Create empty CUs if requested. We do not currently claim that multiple
+ links in succession with CTF_LINK_EMPTY_CU_MAPPINGS set in some calls and
+ not set in others will do anything especially sensible. */
+
+ if (fp->ctf_link_out_cu_mapping && (flags & CTF_LINK_EMPTY_CU_MAPPINGS))
+ {
+ void *v;
+
+ while ((err = ctf_dynhash_next (fp->ctf_link_out_cu_mapping, &i, &v,
+ NULL)) == 0)
+ {
+ const char *to = (const char *) v;
+ if (ctf_create_per_cu (fp, to, to) == NULL)
+ {
+ ctf_next_destroy (i);
+ return -1; /* Errno is set for us. */
+ }
+ }
+ if (err != ECTF_NEXT_END)
+ {
+ ctf_err_warn (fp, 1, "Iteration error creating empty CUs: %s",
+ ctf_errmsg (err));
+ ctf_set_errno (fp, err);
+ return -1;
+ }
+ }
+
ctf_dynhash_iter (fp->ctf_link_inputs, ctf_link_one_input_archive,
&arg);