+#ifdef ENABLE_LIBCTF
+/* Emit CTF errors and warnings. fp can be NULL to report errors/warnings
+ that happened specifically at CTF open time. */
+static void
+lang_ctf_errs_warnings (ctf_dict_t *fp)
+{
+ ctf_next_t *i = NULL;
+ char *text;
+ int is_warning;
+ int err;
+
+ while ((text = ctf_errwarning_next (fp, &i, &is_warning, &err)) != NULL)
+ {
+ einfo (_("%s: %s\n"), is_warning ? _("CTF warning"): _("CTF error"),
+ text);
+ free (text);
+ }
+ if (err != ECTF_NEXT_END)
+ {
+ einfo (_("CTF error: cannot get CTF errors: `%s'\n"),
+ ctf_errmsg (err));
+ }
+
+ /* `err' returns errors from the error/warning iterator in particular.
+ These never assert. But if we have an fp, that could have recorded
+ an assertion failure: assert if it has done so. */
+ ASSERT (!fp || ctf_errno (fp) != ECTF_INTERNAL);
+}
+
+/* Open the CTF sections in the input files with libctf: if any were opened,
+ create a fake input file that we'll write the merged CTF data to later
+ on. */
+
+static void
+ldlang_open_ctf (void)
+{
+ int any_ctf = 0;
+ int err;
+
+ LANG_FOR_EACH_INPUT_STATEMENT (file)
+ {
+ asection *sect;
+
+ /* Incoming files from the compiler have a single ctf_dict_t in them
+ (which is presented to us by the libctf API in a ctf_archive_t
+ wrapper): files derived from a previous relocatable link have a CTF
+ archive containing possibly many CTF files. */
+
+ if ((file->the_ctf = ctf_bfdopen (file->the_bfd, &err)) == NULL)
+ {
+ if (err != ECTF_NOCTFDATA)
+ {
+ lang_ctf_errs_warnings (NULL);
+ einfo (_("%P: warning: CTF section in %pB not loaded; "
+ "its types will be discarded: %s\n"), file->the_bfd,
+ ctf_errmsg (err));
+ }
+ continue;
+ }
+
+ /* Prevent the contents of this section from being written, while
+ requiring the section itself to be duplicated in the output, but only
+ once. */
+ /* This section must exist if ctf_bfdopen() succeeded. */
+ sect = bfd_get_section_by_name (file->the_bfd, ".ctf");
+ sect->size = 0;
+ sect->flags |= SEC_NEVER_LOAD | SEC_HAS_CONTENTS | SEC_LINKER_CREATED;
+
+ if (any_ctf)
+ sect->flags |= SEC_EXCLUDE;
+ any_ctf = 1;
+ }
+
+ if (!any_ctf)
+ {
+ ctf_output = NULL;
+ return;
+ }
+
+ if ((ctf_output = ctf_create (&err)) != NULL)
+ return;
+
+ einfo (_("%P: warning: CTF output not created: `%s'\n"),
+ ctf_errmsg (err));
+
+ LANG_FOR_EACH_INPUT_STATEMENT (errfile)
+ ctf_close (errfile->the_ctf);
+}
+
+/* Merge together CTF sections. After this, only the symtab-dependent
+ function and data object sections need adjustment. */
+
+static void
+lang_merge_ctf (void)
+{
+ asection *output_sect;
+ int flags = 0;
+
+ if (!ctf_output)
+ return;
+
+ output_sect = bfd_get_section_by_name (link_info.output_bfd, ".ctf");
+
+ /* If the section was discarded, don't waste time merging. */
+ if (output_sect == NULL)
+ {
+ ctf_dict_close (ctf_output);
+ ctf_output = NULL;
+
+ LANG_FOR_EACH_INPUT_STATEMENT (file)
+ {
+ ctf_close (file->the_ctf);
+ file->the_ctf = NULL;
+ }
+ return;
+ }
+
+ LANG_FOR_EACH_INPUT_STATEMENT (file)
+ {
+ if (!file->the_ctf)
+ continue;
+
+ /* Takes ownership of file->the_ctf. */
+ if (ctf_link_add_ctf (ctf_output, file->the_ctf, file->filename) < 0)
+ {
+ einfo (_("%P: warning: CTF section in %pB cannot be linked: `%s'\n"),
+ file->the_bfd, ctf_errmsg (ctf_errno (ctf_output)));
+ ctf_close (file->the_ctf);
+ file->the_ctf = NULL;
+ continue;
+ }
+ }
+
+ if (!config.ctf_share_duplicated)
+ flags = CTF_LINK_SHARE_UNCONFLICTED;
+ else
+ flags = CTF_LINK_SHARE_DUPLICATED;
+ if (!config.ctf_variables)
+ flags |= CTF_LINK_OMIT_VARIABLES_SECTION;
+ if (bfd_link_relocatable (&link_info))
+ flags |= CTF_LINK_NO_FILTER_REPORTED_SYMS;
+
+ if (ctf_link (ctf_output, flags) < 0)
+ {
+ lang_ctf_errs_warnings (ctf_output);
+ einfo (_("%P: warning: CTF linking failed; "
+ "output will have no CTF section: %s\n"),
+ ctf_errmsg (ctf_errno (ctf_output)));
+ if (output_sect)
+ {
+ output_sect->size = 0;
+ output_sect->flags |= SEC_EXCLUDE;
+ }
+ }
+ /* Output any lingering errors that didn't come from ctf_link. */
+ lang_ctf_errs_warnings (ctf_output);
+}
+
+/* Let the emulation acquire strings from the dynamic strtab to help it optimize
+ the CTF, if supported. */
+
+void
+ldlang_ctf_acquire_strings (struct elf_strtab_hash *dynstrtab)
+{
+ ldemul_acquire_strings_for_ctf (ctf_output, dynstrtab);
+}
+
+/* Inform the emulation about the addition of a new dynamic symbol, in BFD
+ internal format. */
+void ldlang_ctf_new_dynsym (int symidx, struct elf_internal_sym *sym)
+{
+ ldemul_new_dynsym_for_ctf (ctf_output, symidx, sym);
+}
+
+/* Write out the CTF section. Called early, if the emulation isn't going to
+ need to dedup against the strtab and symtab, then possibly called from the
+ target linker code if the dedup has happened. */
+static void
+lang_write_ctf (int late)
+{
+ size_t output_size;
+ asection *output_sect;
+
+ if (!ctf_output)
+ return;
+
+ if (late)
+ {
+ /* Emit CTF late if this emulation says it can do so. */
+ if (ldemul_emit_ctf_early ())
+ return;
+ }
+ else
+ {
+ if (!ldemul_emit_ctf_early ())
+ return;
+ }
+
+ /* Inform the emulation that all the symbols that will be received have
+ been. */
+
+ ldemul_new_dynsym_for_ctf (ctf_output, 0, NULL);
+
+ /* Emit CTF. */
+
+ output_sect = bfd_get_section_by_name (link_info.output_bfd, ".ctf");
+ if (output_sect)
+ {
+ output_sect->contents = ctf_link_write (ctf_output, &output_size,
+ CTF_COMPRESSION_THRESHOLD);
+ output_sect->size = output_size;
+ output_sect->flags |= SEC_IN_MEMORY | SEC_KEEP;
+
+ lang_ctf_errs_warnings (ctf_output);
+ if (!output_sect->contents)
+ {
+ einfo (_("%P: warning: CTF section emission failed; "
+ "output will have no CTF section: %s\n"),
+ ctf_errmsg (ctf_errno (ctf_output)));
+ output_sect->size = 0;
+ output_sect->flags |= SEC_EXCLUDE;
+ }
+ }
+
+ /* This also closes every CTF input file used in the link. */
+ ctf_dict_close (ctf_output);
+ ctf_output = NULL;
+
+ LANG_FOR_EACH_INPUT_STATEMENT (file)
+ file->the_ctf = NULL;
+}
+
+/* Write out the CTF section late, if the emulation needs that. */
+
+void
+ldlang_write_ctf_late (void)
+{
+ /* Trigger a "late call", if the emulation needs one. */
+
+ lang_write_ctf (1);
+}
+#else
+static void
+ldlang_open_ctf (void)
+{
+ LANG_FOR_EACH_INPUT_STATEMENT (file)
+ {
+ asection *sect;
+
+ /* If built without CTF, warn and delete all CTF sections from the output.
+ (The alternative would be to simply concatenate them, which does not
+ yield a valid CTF section.) */
+
+ if ((sect = bfd_get_section_by_name (file->the_bfd, ".ctf")) != NULL)
+ {
+ einfo (_("%P: warning: CTF section in %pB not linkable: "
+ "%P was built without support for CTF\n"), file->the_bfd);
+ sect->size = 0;
+ sect->flags |= SEC_EXCLUDE;
+ }
+ }
+}
+
+static void lang_merge_ctf (void) {}
+void
+ldlang_ctf_acquire_strings (struct elf_strtab_hash *dynstrtab
+ ATTRIBUTE_UNUSED) {}
+void
+ldlang_ctf_new_dynsym (int symidx ATTRIBUTE_UNUSED,
+ struct elf_internal_sym *sym ATTRIBUTE_UNUSED) {}
+static void lang_write_ctf (int late ATTRIBUTE_UNUSED) {}
+void ldlang_write_ctf_late (void) {}
+#endif
+