aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/ChangeLog5
-rw-r--r--include/ctf-api.h3
-rw-r--r--libctf/ChangeLog19
-rw-r--r--libctf/ctf-link.c250
4 files changed, 46 insertions, 231 deletions
diff --git a/include/ChangeLog b/include/ChangeLog
index 16c14d9..d287b78 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,8 @@
+2021-03-02 Nick Alcock <nick.alcock@oracle.com>
+
+ * ctf-api.h (CTF_LINK_SHARE_DUPLICATED): Note that this might
+ merely change how much deduplication is done.
+
2021-03-01 Alan Modra <amodra@gmail.com>
Fangrui Song <maskray@google.com>
diff --git a/include/ctf-api.h b/include/ctf-api.h
index ce764df..25dbe9e 100644
--- a/include/ctf-api.h
+++ b/include/ctf-api.h
@@ -94,7 +94,8 @@ typedef struct ctf_link_sym
/* Share only types that are used by multiple inputs. */
#define CTF_LINK_SHARE_DUPLICATED 0x1
-/* Do a nondeduplicating link. */
+/* Do a nondeduplicating link, or otherwise deduplicate "less hard", trading off
+ CTF output size for link time. */
#define CTF_LINK_NONDEDUP 0x2
/* Create empty outputs for all registered CU mappings even if no types are
diff --git a/libctf/ChangeLog b/libctf/ChangeLog
index ebfd2f4..5c38c6f 100644
--- a/libctf/ChangeLog
+++ b/libctf/ChangeLog
@@ -1,5 +1,24 @@
2021-03-02 Nick Alcock <nick.alcock@oracle.com>
+ * ctf-link.c (ctf_create_per_cu): Drop FILENAME now that it is
+ always identical to CUNAME.
+ (ctf_link_deduplicating_one_symtypetab): Adjust.
+ (ctf_link_one_type): Remove.
+ (ctf_link_one_input_archive_member): Likewise.
+ (ctf_link_close_one_input_archive): Likewise.
+ (ctf_link_one_input_archive): Likewise.
+ (ctf_link): No longer call it. Drop CTF_LINK_NONDEDUP path.
+ Improve header comment a bit (dicts, not files). Adjust
+ ctf_create_per_cu call.
+ (ctf_link_deduplicating_variables): Simplify.
+ (ctf_link_in_member_cb_arg_t) <cu_name>: Remove.
+ <in_input_cu_file>: Likewise.
+ <in_fp_parent>: Likewise.
+ <done_parent>: Likewise.
+ (ctf_link_one_variable): Turn uses of in_file_name to in_cuname.
+
+2021-03-02 Nick Alcock <nick.alcock@oracle.com>
+
* ctf-types.c (ctf_member_iter): Move 'rc' to an inner scope.
(ctf_enum_iter): Reimplement in terms of ctf_enum_next.
(ctf_type_iter): Reimplement in terms of ctf_type_next.
diff --git a/libctf/ctf-link.c b/libctf/ctf-link.c
index 7c34216..5d813db 100644
--- a/libctf/ctf-link.c
+++ b/libctf/ctf-link.c
@@ -280,29 +280,24 @@ ctf_link_add_ctf (ctf_dict_t *fp, ctf_archive_t *ctf, const char *name)
interning it if need be. */
static ctf_dict_t *
-ctf_create_per_cu (ctf_dict_t *fp, const char *filename, const char *cuname)
+ctf_create_per_cu (ctf_dict_t *fp, const char *cu_name)
{
ctf_dict_t *cu_fp;
const char *ctf_name = NULL;
char *dynname = NULL;
/* First, check the mapping table and translate the per-CU name we use
- accordingly. We check both the input filename and the CU name. Only if
- neither are set do we fall back to the input filename as the per-CU
- dictionary name. We prefer the filename because this is easier for likely
- callers to determine. */
+ accordingly. */
if (fp->ctf_link_in_cu_mapping)
{
- 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;
+ if ((ctf_name = ctf_dynhash_lookup (fp->ctf_link_in_cu_mapping,
+ cu_name)) == NULL)
+ ctf_name = cu_name;
}
if (ctf_name == NULL)
- ctf_name = filename;
+ ctf_name = cu_name;
if ((cu_fp = ctf_dynhash_lookup (fp->ctf_link_outputs, ctf_name)) == NULL)
{
@@ -311,8 +306,7 @@ ctf_create_per_cu (ctf_dict_t *fp, const char *filename, const char *cuname)
if ((cu_fp = ctf_create (&err)) == NULL)
{
ctf_err_warn (fp, 0, err, _("cannot create per-CU CTF archive for "
- "CU %s from input file %s"),
- cuname, filename);
+ "input CU %s"), cu_name);
ctf_set_errno (fp, err);
return NULL;
}
@@ -323,7 +317,7 @@ ctf_create_per_cu (ctf_dict_t *fp, const char *filename, const char *cuname)
goto oom;
ctf_import_unref (cu_fp, fp);
- ctf_cuname_set (cu_fp, cuname);
+ ctf_cuname_set (cu_fp, cu_name);
ctf_parent_name_set (cu_fp, _CTF_SECTION);
}
return cu_fp;
@@ -440,93 +434,16 @@ typedef struct ctf_link_in_member_cb_arg
/* The shared output dictionary. */
ctf_dict_t *out_fp;
- /* The filename of the input file, and an fp to each dictionary in that file
+ /* The cuname of the input file, and an fp to each dictionary in that file
in turn. */
- const char *in_file_name;
+ const char *in_cuname;
ctf_dict_t *in_fp;
- /* The CU name of the dict being processed. */
- const char *cu_name;
- int in_input_cu_file;
-
- /* The parent dictionary in the input, and whether it's been processed yet.
- Not needed by ctf_link_one_type / ctf_link_one_variable, only by higher
- layers. */
- ctf_dict_t *in_fp_parent;
- int done_parent;
-
/* If true, this is the CU-mapped portion of a deduplicating link: no child
dictionaries should be created. */
int cu_mapped;
} ctf_link_in_member_cb_arg_t;
-/* Link one type into the link. We rely on ctf_add_type() to detect
- duplicates. This is not terribly reliable yet (unnmamed types will be
- mindlessly duplicated), but will improve shortly. */
-
-static int
-ctf_link_one_type (ctf_id_t type, int isroot _libctf_unused_, void *arg_)
-{
- ctf_link_in_member_cb_arg_t *arg = (ctf_link_in_member_cb_arg_t *) arg_;
- ctf_dict_t *per_cu_out_fp;
- int err;
-
- if (arg->in_fp->ctf_link_flags != CTF_LINK_SHARE_UNCONFLICTED)
- {
- ctf_err_warn (arg->out_fp, 0, ECTF_NOTYET,
- _("share-duplicated mode not yet implemented"));
- return ctf_set_errno (arg->out_fp, ECTF_NOTYET);
- }
-
- /* Simply call ctf_add_type: if it reports a conflict and we're adding to the
- main CTF file, add to the per-CU archive member instead, creating it if
- necessary. If we got this type from a per-CU archive member, add it
- straight back to the corresponding member in the output. */
-
- if (!arg->in_input_cu_file)
- {
- if (ctf_add_type (arg->out_fp, arg->in_fp, type) != CTF_ERR)
- return 0;
-
- err = ctf_errno (arg->out_fp);
- if (err != ECTF_CONFLICT)
- {
- if (err != ECTF_NONREPRESENTABLE)
- ctf_err_warn (arg->out_fp, 1, 0,
- _("cannot link type %lx from input file %s, CU %s "
- "into output link"), type, arg->cu_name,
- arg->in_file_name);
- /* We must ignore this problem or we end up losing future types, then
- trying to link the variables in, then exploding. Better to link as
- much as possible. */
- return 0;
- }
- ctf_set_errno (arg->out_fp, 0);
- }
-
- if ((per_cu_out_fp = ctf_create_per_cu (arg->out_fp, arg->in_file_name,
- arg->cu_name)) == NULL)
- return -1; /* Errno is set for us. */
-
- if (ctf_add_type (per_cu_out_fp, arg->in_fp, type) != CTF_ERR)
- return 0;
-
- err = ctf_errno (per_cu_out_fp);
- if (err != ECTF_NONREPRESENTABLE)
- ctf_err_warn (arg->out_fp, 1, 0,
- _("cannot link type %lx from input file %s, CU %s "
- "into output per-CU CTF archive member %s: %s: skipped"),
- type, ctf_link_input_name (arg->in_fp), arg->in_file_name,
- ctf_link_input_name (per_cu_out_fp), ctf_errmsg (err));
- if (err == ECTF_CONFLICT)
- /* Conflicts are possible at this stage only if a non-ld user has combined
- multiple TUs into a single output dictionary. Even in this case we do not
- want to stop the link or propagate the error. */
- ctf_set_errno (arg->out_fp, 0);
-
- return 0; /* As above: do not lose types. */
-}
-
/* Set a function which is used to filter out unwanted variables from the link. */
int
ctf_link_set_variable_filter (ctf_dict_t *fp, ctf_link_variable_filter_f *filter,
@@ -615,13 +532,12 @@ ctf_link_one_variable (const char *name, ctf_id_t type, void *arg_)
if (arg->cu_mapped)
{
ctf_dprintf ("Variable %s in input file %s depends on a type %lx hidden "
- "due to conflicts: skipped.\n", name, arg->in_file_name,
+ "due to conflicts: skipped.\n", name, arg->in_cuname,
type);
return 0;
}
- if ((per_cu_out_fp = ctf_create_per_cu (arg->out_fp, arg->in_file_name,
- arg->cu_name)) == NULL)
+ if ((per_cu_out_fp = ctf_create_per_cu (arg->out_fp, arg->in_cuname)) == NULL)
return -1; /* Errno is set for us. */
/* If the type was not found, check for it in the child too. */
@@ -635,7 +551,7 @@ ctf_link_one_variable (const char *name, ctf_id_t type, void *arg_)
ctf_err_warn (arg->out_fp, 1, 0,
_("type %lx for variable %s in input file %s "
"not found: skipped"), type, name,
- arg->in_file_name);
+ arg->in_cuname);
/* Do not terminate the link: just skip the variable. */
return 0;
}
@@ -647,55 +563,6 @@ ctf_link_one_variable (const char *name, ctf_id_t type, void *arg_)
return 0;
}
-/* Merge every type (and optionally, variable) in this archive member into the
- link, so we can relink things that have already had ld run on them. We use
- the archive member name, sans any leading '.ctf.', as the CU name for
- ambiguous types if there is one and it's not the default: otherwise, we use
- the name of the input file. */
-static int
-ctf_link_one_input_archive_member (ctf_dict_t *in_fp, const char *name, void *arg_)
-{
- ctf_link_in_member_cb_arg_t *arg = (ctf_link_in_member_cb_arg_t *) arg_;
- int err = 0;
-
- if (strcmp (name, _CTF_SECTION) == 0)
- {
- /* This file is the default member of this archive, and has already been
- explicitly processed.
-
- In the default sharing mode of CTF_LINK_SHARE_UNCONFLICTED, it does no
- harm to rescan an existing shared repo again: all the types will just
- end up in the same place. But in CTF_LINK_SHARE_DUPLICATED mode, this
- causes the system to erroneously conclude that all types are duplicated
- and should be shared, even if they are not. */
-
- if (arg->done_parent)
- return 0;
- }
- else
- {
- /* Get ambiguous types from our parent. */
- ctf_import (in_fp, arg->in_fp_parent);
- arg->in_input_cu_file = 1;
- }
-
- arg->cu_name = name;
- if (strncmp (arg->cu_name, ".ctf.", strlen (".ctf.")) == 0)
- arg->cu_name += strlen (".ctf.");
- arg->in_fp = in_fp;
-
- if ((err = ctf_type_iter_all (in_fp, ctf_link_one_type, arg)) > -1)
- if (!(in_fp->ctf_link_flags & CTF_LINK_OMIT_VARIABLES_SECTION))
- err = ctf_variable_iter (in_fp, ctf_link_one_variable, arg);
-
- arg->in_input_cu_file = 0;
-
- if (err < 0)
- return -1; /* Errno is set for us. */
-
- return 0;
-}
-
/* Dump the unnecessary link type mapping after one input file is processed. */
static void
empty_link_type_mapping (void *key _libctf_unused_, void *value,
@@ -753,73 +620,6 @@ ctf_link_lazy_open (ctf_dict_t *fp, ctf_link_input_t *input)
return (ssize_t) count;
}
-/* Close an input, as a ctf_dynhash_iter iterator. */
-static void
-ctf_link_close_one_input_archive (void *key _libctf_unused_, void *value,
- void *arg _libctf_unused_)
-{
- ctf_link_input_t *input = (ctf_link_input_t *) value;
- if (input->clin_arc)
- ctf_arc_close (input->clin_arc);
- input->clin_arc = NULL;
-}
-
-/* Link one input file's types into the output file. */
-static void
-ctf_link_one_input_archive (void *key, void *value, void *arg_)
-{
- const char *file_name = (const char *) key;
- ctf_link_input_t *input = (ctf_link_input_t *)value;
- ctf_link_in_member_cb_arg_t *arg = (ctf_link_in_member_cb_arg_t *) arg_;
- int err = 0;
-
- if (!input->clin_arc)
- {
- err = ctf_link_lazy_open (arg->out_fp, input);
- if (err == 0) /* Just no CTF. */
- return;
-
- if (err < 0)
- return; /* errno is set for us. */
- }
-
- arg->in_file_name = file_name;
- arg->done_parent = 0;
- if ((arg->in_fp_parent = ctf_dict_open (input->clin_arc,
- NULL, &err)) == NULL)
- if (err != ECTF_ARNNAME)
- {
- ctf_err_warn (arg->out_fp, 1, 0,
- _("cannot open main archive member in input file %s "
- "in the link: skipping: %s"), arg->in_file_name,
- ctf_errmsg (err));
- goto out;
- }
-
- if (ctf_link_one_input_archive_member (arg->in_fp_parent,
- _CTF_SECTION, arg) < 0)
- {
- ctf_dict_close (arg->in_fp_parent);
- goto out;
- }
- arg->done_parent = 1;
- if (ctf_archive_iter (input->clin_arc, ctf_link_one_input_archive_member,
- arg) < 0)
- ctf_err_warn (arg->out_fp, 0, 0, _("cannot traverse archive in input file "
- "%s: link cannot continue"),
- arg->in_file_name);
- else
- {
- /* The only error indication to the caller is the errno: so ensure that it
- is zero if there was no actual error from the caller. */
- ctf_set_errno (arg->out_fp, 0);
- }
- ctf_dict_close (arg->in_fp_parent);
-
- out:
- ctf_link_close_one_input_archive (key, value, NULL);
-}
-
typedef struct link_sort_inputs_cb_arg
{
int is_cu_mapped;
@@ -1130,21 +930,16 @@ ctf_link_deduplicating_variables (ctf_dict_t *fp, ctf_dict_t **inputs,
arg.cu_mapped = cu_mapped;
arg.out_fp = fp;
- arg.in_input_cu_file = 0;
for (i = 0; i < ninputs; i++)
{
arg.in_fp = inputs[i];
if (ctf_cuname (inputs[i]) != NULL)
- arg.in_file_name = ctf_cuname (inputs[i]);
+ arg.in_cuname = ctf_cuname (inputs[i]);
else
- arg.in_file_name = "unnamed-CU";
- arg.cu_name = arg.in_file_name;
+ arg.in_cuname = "unnamed-CU";
if (ctf_variable_iter (arg.in_fp, ctf_link_one_variable, &arg) < 0)
return ctf_set_errno (fp, ctf_errno (arg.in_fp));
-
- /* Outputs > 0 are per-CU. */
- arg.in_input_cu_file = 1;
}
return 0;
}
@@ -1237,8 +1032,7 @@ ctf_link_deduplicating_one_symtypetab (ctf_dict_t *fp, ctf_dict_t *input,
continue;
}
- if ((per_cu_out_fp = ctf_create_per_cu (fp, in_file_name,
- in_file_name)) == NULL)
+ if ((per_cu_out_fp = ctf_create_per_cu (fp, in_file_name)) == NULL)
return -1; /* errno is set for us. */
/* If the type was not found, check for it in the child too. */
@@ -1653,8 +1447,8 @@ ctf_link_deduplicating (ctf_dict_t *fp)
goto err;
}
-/* Merge types and variable sections in all files added to the link
- together. All the added files are closed. */
+/* Merge types and variable sections in all dicts added to the link together.
+ All the added dicts are closed. */
int
ctf_link (ctf_dict_t *fp, int flags)
{
@@ -1691,7 +1485,7 @@ ctf_link (ctf_dict_t *fp, int flags)
NULL)) == 0)
{
const char *to = (const char *) v;
- if (ctf_create_per_cu (fp, to, to) == NULL)
+ if (ctf_create_per_cu (fp, to) == NULL)
{
fp->ctf_flags &= ~LCTF_LINKING;
ctf_next_destroy (i);
@@ -1707,11 +1501,7 @@ ctf_link (ctf_dict_t *fp, int flags)
}
}
- if ((flags & CTF_LINK_NONDEDUP) || (getenv ("LD_NO_CTF_DEDUP")))
- ctf_dynhash_iter (fp->ctf_link_inputs, ctf_link_one_input_archive,
- &arg);
- else
- ctf_link_deduplicating (fp);
+ ctf_link_deduplicating (fp);
/* Discard the now-unnecessary mapping table data from all the outputs. */
if (fp->ctf_link_type_mapping)