+2019-07-13  Nick Alcock  <nick.alcock@oracle.com>
+
+       * Makefile.def (dependencies): all-ld depends on all-libctf.
+       * Makefile.in: Regenerated.
+
 2019-09-09  Phil Blundell  <pb@pbcl.net>
 
        binutils 2.33 branch created
 
 dependencies = { module=all-binutils; on=all-intl; };
 dependencies = { module=all-binutils; on=all-gas; };
 dependencies = { module=all-binutils; on=all-libctf; };
+dependencies = { module=all-ld; on=all-libctf; };
 
 // We put install-opcodes before install-binutils because the installed
 // binutils might be on PATH, and they might need the shared opcodes
 
 all-stage4-binutils: maybe-all-stage4-libctf
 all-stageprofile-binutils: maybe-all-stageprofile-libctf
 all-stagefeedback-binutils: maybe-all-stagefeedback-libctf
+all-ld: maybe-all-libctf
+all-stage1-ld: maybe-all-stage1-libctf
+all-stage2-ld: maybe-all-stage2-libctf
+all-stage3-ld: maybe-all-stage3-libctf
+all-stage4-ld: maybe-all-stage4-libctf
+all-stageprofile-ld: maybe-all-stageprofile-libctf
+all-stagefeedback-ld: maybe-all-stagefeedback-libctf
 install-binutils: maybe-install-opcodes
 install-strip-binutils: maybe-install-strip-opcodes
 install-opcodes: maybe-install-bfd
 
+2019-09-30  Nick Alcock  <nick.alcock@oracle.com>
+
+       * elf-bfd.h (bfd_section_is_ctf): New inline function.
+       * elf.c (special_sections_c): Add ".ctf".
+       (assign_file_positions_for_non_load_sections): Note that
+       compressed debugging sections etc are not assigned here.  Treat
+       CTF sections like SEC_ELF_COMPRESS sections when is_linker_output:
+       sh_offset -1.
+       (assign_file_positions_except_relocs): Likewise.
+       (find_section_in_list): Note that debugging and CTF sections, as
+       well as reloc sections, are assigned later.
+       (_bfd_elf_assign_file_positions_for_non_load): CTF sections get
+       their size and contents updated.
+       (_bfd_elf_set_section_contents): Skip CTF sections: unlike
+       compressed sections, they have no uncompressed content to copy at
+       this stage.
+       * elflink.c (elf_link_swap_symbols_out): Call the examine_strtab
+       callback right before the strtab is written out.
+       (bfd_elf_final_link): Don't cache the section contents of CTF
+       sections: they are not populated yet.  Call the emit_ctf callback
+       right at the end, after all the symbols and strings are flushed
+       out.
+
 2019-07-13  Nick Alcock  <nick.alcock@oracle.com>
 
        * elf-strtab.c (_bfd_elf_strtab_len): New.
 
 extern bfd_size_type _bfd_elf_strtab_offset
   (struct elf_strtab_hash *, size_t);
 extern const char * _bfd_elf_strtab_str
-  (struct elf_strtab_hash *, size_t idx, size_t *offset);
+  (struct elf_strtab_hash *, size_t idx, bfd_size_type *offset);
 extern bfd_boolean _bfd_elf_strtab_emit
   (bfd *, struct elf_strtab_hash *);
 extern void _bfd_elf_strtab_finalize
         || (H)->start_stop \
         || ((INFO)->dynamic && !(H)->dynamic)))
 
+/* Determine if a section contains CTF data, using its name.  */
+static inline bfd_boolean
+bfd_section_is_ctf (const asection *sec)
+{
+  const char *name = bfd_section_name (sec);
+  return strncmp (name, ".ctf", 4) == 0 && (name[4] == 0 || name[4] == '.');
+}
+
 #ifdef __cplusplus
 }
 #endif
 
 static const struct bfd_elf_special_section special_sections_c[] =
 {
   { STRING_COMMA_LEN (".comment"), 0, SHT_PROGBITS, 0 },
+  { STRING_COMMA_LEN (".ctf"), 0, SHT_PROGBITS,    0 },
   { NULL,                      0, 0, 0,            0 }
 };
 
   return TRUE;
 }
 
-/* Assign file positions for the other sections.  */
+/* Assign file positions for the other sections, except for compressed debugging
+   and other sections assigned in _bfd_elf_assign_file_positions_for_non_load().  */
 
 static bfd_boolean
 assign_file_positions_for_non_load_sections (bfd *abfd,
        }
       else if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA)
                && hdr->bfd_section == NULL)
+              /* We don't know the offset of these sections yet: their size has
+                 not been decided.  */
               || (hdr->bfd_section != NULL
-                  && (hdr->bfd_section->flags & SEC_ELF_COMPRESS))
-                  /* Compress DWARF debug sections.  */
+                  && (hdr->bfd_section->flags & SEC_ELF_COMPRESS
+                      || (bfd_section_is_ctf (hdr->bfd_section)
+                          && abfd->is_linker_output)))
               || hdr == i_shdrpp[elf_onesymtab (abfd)]
               || (elf_symtab_shndx_list (abfd) != NULL
                   && hdr == i_shdrpp[elf_symtab_shndx_list (abfd)->ndx])
    VMAs must be known before this is called.
 
    Reloc sections come in two flavours: Those processed specially as
-   "side-channel" data attached to a section to which they apply, and
-   those that bfd doesn't process as relocations.  The latter sort are
-   stored in a normal bfd section by bfd_section_from_shdr.   We don't
-   consider the former sort here, unless they form part of the loadable
-   image.  Reloc sections not assigned here will be handled later by
+   "side-channel" data attached to a section to which they apply, and those that
+   bfd doesn't process as relocations.  The latter sort are stored in a normal
+   bfd section by bfd_section_from_shdr.  We don't consider the former sort
+   here, unless they form part of the loadable image.  Reloc sections not
+   assigned here (and compressed debugging sections and CTF sections which
+   nothing else in the file can rely upon) will be handled later by
    assign_file_positions_for_relocs.
 
    We also don't set the positions of the .symtab and .strtab here.  */
          hdr = *hdrpp;
          if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA)
               && hdr->bfd_section == NULL)
+             /* Do not assign offsets for these sections yet: we don't know
+                their sizes.  */
              || (hdr->bfd_section != NULL
-                 && (hdr->bfd_section->flags & SEC_ELF_COMPRESS))
-                 /* Compress DWARF debug sections.  */
+                 && (hdr->bfd_section->flags & SEC_ELF_COMPRESS
+                     || (bfd_section_is_ctf (hdr->bfd_section)
+                         && abfd->is_linker_output)))
              || i == elf_onesymtab (abfd)
              || (elf_symtab_shndx_list (abfd) != NULL
                  && hdr == i_shdrpp[elf_symtab_shndx_list (abfd)->ndx])
          asection *sec = shdrp->bfd_section;
          bfd_boolean is_rel = (shdrp->sh_type == SHT_REL
                                || shdrp->sh_type == SHT_RELA);
+         bfd_boolean is_ctf = sec && bfd_section_is_ctf (sec);
          if (is_rel
+             || is_ctf
              || (sec != NULL && (sec->flags & SEC_ELF_COMPRESS)))
            {
-             if (!is_rel)
+             if (!is_rel && !is_ctf)
                {
                  const char *name = sec->name;
                  struct bfd_elf_section_data *d;
                  shdrp->contents = sec->contents;
                  shdrp->bfd_section->contents = NULL;
                }
+             else if (is_ctf)
+               {
+                 /* Update section size and contents.  */
+                 shdrp->sh_size = sec->size;
+                 shdrp->contents = sec->contents;
+               }
+
              off = _bfd_elf_assign_file_position_for_section (shdrp,
                                                               off,
                                                               TRUE);
   hdr = &elf_section_data (section)->this_hdr;
   if (hdr->sh_offset == (file_ptr) -1)
     {
+      if (bfd_section_is_ctf (section))
+       /* Nothing to do with this section: the contents are generated
+          later.  */
+       return TRUE;
+
       /* We must compress this section.  Write output to the buffer.  */
       unsigned char *contents = hdr->contents;
       if ((offset + count) > hdr->sh_size
 
                                + elfsym->destshndx_index));
     }
 
+  /* Allow the linker to examine the strtab and symtab now they are
+     populated.  */
+
+  if (flinfo->info->callbacks->examine_strtab)
+    flinfo->info->callbacks->examine_strtab (hash_table->strtab,
+                                            hash_table->strtabcount,
+                                            flinfo->symstrtab);
+
   hdr = &elf_tdata (flinfo->output_bfd)->symtab_hdr;
   pos = hdr->sh_offset + hdr->sh_size;
   amt = hash_table->strtabcount * bed->s->sizeof_sym;
 
   /* The object attributes have been merged.  Remove the input
      sections from the link, and set the contents of the output
-     secton.  */
+     section.  */
   std_attrs_section = get_elf_backend_data (abfd)->obj_attrs_section;
   for (o = abfd->sections; o != NULL; o = o->next)
     {
       esdo->rel.count = 0;
       esdo->rela.count = 0;
 
-      if (esdo->this_hdr.sh_offset == (file_ptr) -1)
+      if ((esdo->this_hdr.sh_offset == (file_ptr) -1)
+         && !bfd_section_is_ctf (o))
        {
          /* Cache the section contents so that they can be compressed
             later.  Use bfd_malloc since it will be freed by
        }
     }
 
-  /* We have now assigned file positions for all the sections except
-     .symtab, .strtab, and non-loaded reloc sections.  We start the
-     .symtab section at the current file position, and write directly
-     to it.  We build the .strtab section in memory.  */
+  /* We have now assigned file positions for all the sections except .symtab,
+     .strtab, and non-loaded reloc and compressed debugging sections.  We start
+     the .symtab section at the current file position, and write directly to it.
+     We build the .strtab section in memory.  */
   abfd->symcount = 0;
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   /* sh_name is set in prep_headers.  */
   if (! _bfd_elf_write_section_eh_frame_hdr (abfd, info))
     goto error_return;
 
+  if (info->callbacks->emit_ctf)
+      info->callbacks->emit_ctf ();
+
   elf_final_link_free (abfd, &flinfo);
 
   if (attr_section)
 
+2019-07-13  Nick Alcock  <nick.alcock@oracle.com>
+
+       * bfdlink.h (elf_strtab_hash): New forward.
+       (elf_sym_strtab): Likewise.
+       (struct bfd_link_callbacks <examine_strtab>): New.
+       (struct bfd_link_callbacks <emit_ctf>): Likewise.
+
 2019-07-13  Nick Alcock  <nick.alcock@oracle.com>
 
        * ctf-api.h (includes): No longer include <sys/param.h>.
 
   struct bfd_elf_version_tree *version_info;
 };
 
+/* Some forward-definitions used by some callbacks.  */
+
+struct elf_strtab_hash;
+struct elf_sym_strtab;
+
 /* This structures holds a set of callback functions.  These are called
    by the BFD linker routines.  */
 
     (struct bfd_link_info *, bfd * abfd,
      asection * current_section, asection * previous_section,
      bfd_boolean new_segment);
+  /* This callback provides a chance for callers of the BFD to examine the
+     ELF string table and symbol table once they are complete and indexes and
+     offsets assigned.  */
+  void (*examine_strtab)
+    (struct elf_sym_strtab *syms, bfd_size_type symcount,
+     struct elf_strtab_hash *symstrtab);
+  /* This callback should emit the CTF section into a non-loadable section in
+     the output BFD named .ctf or a name beginning with ".ctf.".  */
+  void (*emit_ctf)
+    (void);
 };
 \f
 /* The linker builds link_order structures which tell the code how to
 
+2019-09-30  Nick Alcock  <nick.alcock@oracle.com>
+
+       * ldlang.h: (struct lang_input_statement_struct): Add the_ctf.
+       (struct elf_sym_strtab): Add forward.
+       (struct elf_strtab_hash): Likewise.
+       (ldlang_ctf_apply_strsym): Declare.
+       (ldlang_write_ctf_late): Likewise.
+       * ldemul.h (ldemul_emit_ctf_early): New.
+       (ldemul_examine_strtab_for_ctf): Likewise.
+       (ld_emulation_xfer_type) <emit_ctf_early>: Likewise.
+       (ld_emulation_xfer_type) <examine_strtab_for_ctf>: Likewise.
+       * ldemul.c (ldemul_emit_ctf_early): New.
+       (ldemul_examine_strtab_for_ctf): Likewise.
+       * ldlang.c: Include ctf-api.h.
+       (CTF_COMPRESSION_THRESHOLD): New.
+       (ctf_output): New. Initialized in...
+       (ldlang_open_ctf): ... this new function.  Open all the CTF
+       sections in the input files: mark them non-loaded and empty
+       so as not to copy their contents to the output, but linker-created
+       so the section gets created in the target.
+       (ldlang_merge_ctf): New, merge types via ctf_link_add_ctf and
+       ctf_link.
+       (ldlang_ctf_apply_strsym): New, an examine_strtab callback: wrap
+       ldemul_examine_strtab_for_ctf.
+       (lang_write_ctf): New, write out the CTF section.
+       (ldlang_write_ctf_late): New, late call via bfd's emit_ctf hook.
+       (lang_process): Call ldlang_open_ctf, ldlang_merge_ctf, and
+       lang_write_ctf.
+       * ldmain.c (link_callbacks): Add ldlang_ctf_apply_strsym,
+       ldlang_write_ctf_late.
+       * emultempl/aix.em: Add ctf-api.h.
+       * emultempl/armcoff.em: Likewise.
+       * emultempl/beos.em: Likewise.
+       * emultempl/elf.em: Likewise.
+       * emultempl/generic.em: Likewise.
+       * emultempl/linux.em: Likewise.
+       * emultempl/msp430.em: Likewise.
+       * emultempl/pe.em: Likewise.
+       * emultempl/pep.em: Likewise.
+       * emultempl/ticoff.em: Likewise.
+       * emultempl/vanilla.em: Likewise.
+       * ldcref.c: Likewise.
+       * ldctor.c: Likewise.
+       * ldelf.c: Likewise.
+       * ldelfgen.c: Likewise.
+       * ldemul.c: Likewise.
+       * ldexp.c: Likewise.
+       * ldfile.c: Likewise.
+       * ldgram.c: Likewise.
+       * ldlex.l: Likewise.
+       * ldmain.c: Likewise.
+       * ldmisc.c: Likewise.
+       * ldver.c: Likewise.
+       * ldwrite.c: Likewise.
+       * lexsup.c: Likewise.
+       * mri.c: Likewise.
+       * pe-dll.c: Likewise.
+       * plugin.c: Likewise.
+
+       * ldelfgen.c (ldelf_emit_ctf_early): New.
+       (ldelf_examine_strtab_for_ctf): tell libctf about the symtab and
+       strtab.
+       (struct ctf_strsym_iter_cb_arg): New, state to do so.
+       (ldelf_ctf_strtab_iter_cb): New: tell libctf about
+       each string in the strtab in turn.
+       (ldelf_ctf_symbols_iter_cb): New, tell libctf
+       about each symbol in the symtab in turn.
+       * ldelfgen.h (struct elf_sym_strtab): Add forward.
+       (struct elf_strtab_hash): Likewise.
+       (struct ctf_file): Likewise.
+       (ldelf_emit_ctf_early): Declare.
+       (ldelf_examine_strtab_for_ctf): Likewise.
+       * emultempl/elf-generic.em (LDEMUL_EMIT_CTF_EARLY): Set it.
+       (LDEMUL_EXAMINE_STRTAB_FOR_CTF): Likewise.
+       * emultempl/aix.em (ld_${EMULATION_NAME}_emulation): Add
+       emit_ctf_early and examine_strtab_for_ctf, NULL by default.
+       * emultempl/armcoff.em (ld_${EMULATION_NAME}_emulation): Likewise.
+       * emultempl/beos.em (ld_${EMULATION_NAME}_emulation): Likewise.
+       * emultempl/elf.em (ld_${EMULATION_NAME}_emulation): Likewise.
+       * emultempl/generic.em (ld_${EMULATION_NAME}_emulation): Likewise.
+       * emultempl/linux.em (ld_${EMULATION_NAME}_emulation): Likewise.
+       * emultempl/msp430.em (ld_${EMULATION_NAME}_emulation): Likewise.
+       * emultempl/pe.em (ld_${EMULATION_NAME}_emulation): Likewise.
+       * emultempl/pep.em (ld_${EMULATION_NAME}_emulation): Likewise.
+       * emultempl/ticoff.em (ld_${EMULATION_NAME}_emulation): Likewise.
+       * emultempl/vanilla.em (ld_vanilla_emulation): Likewise.
+
+       * Makefile.am: Pull in libctf (and zlib, a transitive requirement
+       for compressed CTF section emission).  Pass it on to DejaGNU.
+       * configure.ac: Add AM_ZLIB.
+       * aclocal.m4: Added zlib.m4.
+       * Makefile.in: Regenerated.
+       * testsuite/ld-bootstrap/bootstrap.exp: Use it when relinking ld.
+
 2019-10-02  Alan Modra  <amodra@gmail.com>
 
        * ld.texi (-Bsymbolic, -Bsymbolic-functions): Don't mention PIEs.
 
 am__skiplex =
 am__skipyacc =
 
+# This is where we get zlib from.  zlibdir is -L../zlib and zlibinc is
+# -I../zlib, unless we were configured with --with-system-zlib, in which
+# case both are empty.
+ZLIB = @zlibdir@ -lz
+ZLIBINC = @zlibinc@
+
 ELF_CLFAGS=-DELF_LIST_OPTIONS=@elf_list_options@ \
           -DELF_SHLIB_LIST_OPTIONS=@elf_shlib_list_options@ \
           -DELF_PLT_UNWIND_LIST_OPTIONS=@elf_plt_unwind_list_options@
 TEXI2DVI = texi2dvi -I $(srcdir) -I $(BFDDIR)/doc -I ../bfd/doc \
                    -I $(top_srcdir)/../libiberty
 
-AM_CPPFLAGS = -I. -I$(srcdir) -I../bfd -I$(BFDDIR) -I$(INCDIR) \
+AM_CPPFLAGS = -I. -I$(srcdir) -I../bfd -I$(BFDDIR) -I$(INCDIR) @zlibinc@ \
        @INCINTL@ $(HDEFINES) $(CFLAGS) $(PLUGIN_CFLAGS) \
        -DLOCALEDIR="\"$(datadir)/locale\""
 
 BFDLIB = ../bfd/libbfd.la
 LIBIBERTY = ../libiberty/libiberty.a
+LIBCTF = ../libctf/libctf.a
 
 # These all start with e so 'make clean' can find them.
 ALL_EMULATION_SOURCES = \
        ldwrite.c ldexp.c ldemul.c ldver.c ldmisc.c ldfile.c ldcref.c $(PLUGIN_C) \
        ldbuildid.c
 ld_new_DEPENDENCIES = $(EMULATION_OFILES) $(EMUL_EXTRA_OFILES) \
-                     $(BFDLIB) $(LIBIBERTY) $(LIBINTL_DEP)
-ld_new_LDADD = $(EMULATION_OFILES) $(EMUL_EXTRA_OFILES) $(BFDLIB) $(LIBIBERTY) $(LIBINTL)
+                     $(BFDLIB) $(LIBCTF) $(LIBIBERTY) $(LIBINTL_DEP)
+ld_new_LDADD = $(EMULATION_OFILES) $(EMUL_EXTRA_OFILES) $(BFDLIB) $(LIBCTF) $(LIBIBERTY) $(LIBINTL) $(ZLIB)
 
 # Dependency tracking for the generated emulation files.
 EXTRA_ld_new_SOURCES += $(ALL_EMULATION_SOURCES) $(ALL_64_EMULATION_SOURCES)
                CC="$(CC_FOR_TARGET)" CFLAGS="$(CFLAGS_FOR_TARGET)" \
                CXX="$(CXX_FOR_TARGET)" CXXFLAGS="$(CXXFLAGS_FOR_TARGET)" \
                CC_FOR_HOST="$(CC)" CFLAGS_FOR_HOST="$(CFLAGS)" \
-               OFILES="$(OFILES)" BFDLIB="$(TESTBFDLIB)" \
+               OFILES="$(OFILES)" BFDLIB="$(TESTBFDLIB)" CTFLIB="$(LIBCTF) $(ZLIB)" \
                LIBIBERTY="$(LIBIBERTY) $(LIBINTL)" LIBS="$(LIBS)" \
                DO_COMPARE="`echo '$(do_compare)' | sed -e 's,\\$$,,g'`" \
                $(RUNTESTFLAGS); \
 
        $(top_srcdir)/../config/plugins.m4 \
        $(top_srcdir)/../config/po.m4 \
        $(top_srcdir)/../config/progtest.m4 \
-       $(top_srcdir)/../libtool.m4 $(top_srcdir)/../ltoptions.m4 \
-       $(top_srcdir)/../ltsugar.m4 $(top_srcdir)/../ltversion.m4 \
-       $(top_srcdir)/../lt~obsolete.m4 \
+       $(top_srcdir)/../config/zlib.m4 $(top_srcdir)/../libtool.m4 \
+       $(top_srcdir)/../ltoptions.m4 $(top_srcdir)/../ltsugar.m4 \
+       $(top_srcdir)/../ltversion.m4 $(top_srcdir)/../lt~obsolete.m4 \
        $(top_srcdir)/../bfd/version.m4 $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
        $(ACLOCAL_M4)
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 use_sysroot = @use_sysroot@
+zlibdir = @zlibdir@
+zlibinc = @zlibinc@
 AUTOMAKE_OPTIONS = dejagnu no-texinfo.tex no-dist foreign info-in-builddir
 ACLOCAL_AMFLAGS = -I .. -I ../config -I ../bfd
 TEXINFO_TEX = ../texinfo/texinfo.tex
 # maintainer mode is disabled.  Avoid this.
 am__skiplex = 
 am__skipyacc = 
+
+# This is where we get zlib from.  zlibdir is -L../zlib and zlibinc is
+# -I../zlib, unless we were configured with --with-system-zlib, in which
+# case both are empty.
+ZLIB = @zlibdir@ -lz
+ZLIBINC = @zlibinc@
 ELF_CLFAGS = -DELF_LIST_OPTIONS=@elf_list_options@ \
           -DELF_SHLIB_LIST_OPTIONS=@elf_shlib_list_options@ \
           -DELF_PLT_UNWIND_LIST_OPTIONS=@elf_plt_unwind_list_options@
 TEXI2DVI = texi2dvi -I $(srcdir) -I $(BFDDIR)/doc -I ../bfd/doc \
                    -I $(top_srcdir)/../libiberty
 
-AM_CPPFLAGS = -I. -I$(srcdir) -I../bfd -I$(BFDDIR) -I$(INCDIR) \
+AM_CPPFLAGS = -I. -I$(srcdir) -I../bfd -I$(BFDDIR) -I$(INCDIR) @zlibinc@ \
        @INCINTL@ $(HDEFINES) $(CFLAGS) $(PLUGIN_CFLAGS) \
        -DLOCALEDIR="\"$(datadir)/locale\""
 
 BFDLIB = ../bfd/libbfd.la
 LIBIBERTY = ../libiberty/libiberty.a
+LIBCTF = ../libctf/libctf.a
 
 # These all start with e so 'make clean' can find them.
 ALL_EMULATION_SOURCES = \
        ldbuildid.c
 
 ld_new_DEPENDENCIES = $(EMULATION_OFILES) $(EMUL_EXTRA_OFILES) \
-                     $(BFDLIB) $(LIBIBERTY) $(LIBINTL_DEP)
+                     $(BFDLIB) $(LIBCTF) $(LIBIBERTY) $(LIBINTL_DEP)
 
-ld_new_LDADD = $(EMULATION_OFILES) $(EMUL_EXTRA_OFILES) $(BFDLIB) $(LIBIBERTY) $(LIBINTL)
+ld_new_LDADD = $(EMULATION_OFILES) $(EMUL_EXTRA_OFILES) $(BFDLIB) $(LIBCTF) $(LIBIBERTY) $(LIBINTL) $(ZLIB)
 #
 #
 # Build a dummy plugin using libtool.
                CC="$(CC_FOR_TARGET)" CFLAGS="$(CFLAGS_FOR_TARGET)" \
                CXX="$(CXX_FOR_TARGET)" CXXFLAGS="$(CXXFLAGS_FOR_TARGET)" \
                CC_FOR_HOST="$(CC)" CFLAGS_FOR_HOST="$(CFLAGS)" \
-               OFILES="$(OFILES)" BFDLIB="$(TESTBFDLIB)" \
+               OFILES="$(OFILES)" BFDLIB="$(TESTBFDLIB)" CTFLIB="$(LIBCTF) $(ZLIB)" \
                LIBIBERTY="$(LIBIBERTY) $(LIBINTL)" LIBS="$(LIBS)" \
                DO_COMPARE="`echo '$(do_compare)' | sed -e 's,\\$$,,g'`" \
                $(RUNTESTFLAGS); \
 
 m4_include([../config/plugins.m4])
 m4_include([../config/po.m4])
 m4_include([../config/progtest.m4])
+m4_include([../config/zlib.m4])
 m4_include([../libtool.m4])
 m4_include([../ltoptions.m4])
 m4_include([../ltsugar.m4])
 
 elf_shlib_list_options
 elf_list_options
 STRINGIFY
+zlibinc
+zlibdir
 enable_initfini_array
 ENABLE_PLUGINS_FALSE
 ENABLE_PLUGINS_TRUE
 enable_build_warnings
 enable_nls
 enable_initfini_array
+with_system_zlib
 '
       ac_precious_vars='build_alias
 host_alias
   --with-gnu-ld           assume the C compiler uses GNU ld [default=no]
   --with-lib-path=dir1:dir2...  set default LIB_PATH
   --with-sysroot=DIR Search for usr/lib et al within DIR.
+  --with-system-zlib      use installed libz
 
 Some influential environment variables:
   CC          C compiler command
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12030 "configure"
+#line 12034 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12136 "configure"
+#line 12140 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
 _ACEOF
 
 
+# Link in zlib if we can.  This allows us to read and write
+# compressed CTF sections.
+
+  # Use the system's zlib library.
+  zlibdir="-L\$(top_builddir)/../zlib"
+  zlibinc="-I\$(top_srcdir)/../zlib"
+
+# Check whether --with-system-zlib was given.
+if test "${with_system_zlib+set}" = set; then :
+  withval=$with_system_zlib; if test x$with_system_zlib = xyes ; then
+    zlibdir=
+    zlibinc=
+  fi
+
+fi
+
+
+
+
+
 # When converting linker scripts into strings for use in emulation
 # files, use astring.sed if the compiler supports ANSI string
 # concatenation, or ostring.sed otherwise.  This is to support the
 
 
 AC_CHECK_DECLS([strstr, free, sbrk, getenv, environ])
 
+# Link in zlib if we can.  This allows us to read and write
+# compressed CTF sections.
+AM_ZLIB
+
 # When converting linker scripts into strings for use in emulation
 # files, use astring.sed if the compiler supports ANSI string
 # concatenation, or ostring.sed otherwise.  This is to support the
 
 #include "getopt.h"
 #include "obstack.h"
 #include "bfdlink.h"
+#include "ctf-api.h"
 
 #include "ld.h"
 #include "ldmain.h"
   NULL,                                /* recognized_file */
   NULL,                                /* find potential_libraries */
   NULL,                                /* new_vers_pattern */
-  NULL                         /* extra_map_file_text */
+  NULL,                                /* extra_map_file_text */
+  ${LDEMUL_EMIT_CTF_EARLY-NULL},
+  ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}
 };
 EOF
 
 #include "sysdep.h"
 #include "bfd.h"
 #include "bfdlink.h"
+#include "ctf-api.h"
 #include "getopt.h"
 
 #include "ld.h"
   NULL,        /* recognized file */
   NULL,        /* find_potential_libraries */
   NULL,        /* new_vers_pattern */
-  NULL /* extra_map_file_text */
+  NULL,        /* extra_map_file_text */
+  ${LDEMUL_EMIT_CTF_EARLY-NULL},
+  ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}
 };
 EOF
 
 #include "sysdep.h"
 #include "bfd.h"
 #include "bfdlink.h"
+#include "ctf-api.h"
 #include "getopt.h"
 #include "libiberty.h"
 #include "filenames.h"
   NULL,        /* recognized file */
   NULL,        /* find_potential_libraries */
   NULL,        /* new_vers_pattern */
-  NULL /* extra_map_file_text */
+  NULL,        /* extra_map_file_text */
+  ${LDEMUL_EMIT_CTF_EARLY-NULL},
+  ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}
 };
 EOF
 
 fragment <<EOF
 
 EOF
+# Put these extra routines in ld${EMULATION_NAME}_emulation
+#
+LDEMUL_EMIT_CTF_EARLY=ldelf_emit_ctf_early
+LDEMUL_EXAMINE_STRTAB_FOR_CTF=ldelf_examine_strtab_for_ctf
 
 #include "libiberty.h"
 #include "getopt.h"
 #include "bfdlink.h"
+#include "ctf-api.h"
 #include "ld.h"
 #include "ldmain.h"
 #include "ldmisc.h"
   ${LDEMUL_RECOGNIZED_FILE-ldelf_load_symbols},
   ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL},
   ${LDEMUL_NEW_VERS_PATTERN-NULL},
-  ${LDEMUL_EXTRA_MAP_FILE_TEXT-NULL}
+  ${LDEMUL_EXTRA_MAP_FILE_TEXT-NULL},
+  ${LDEMUL_EMIT_CTF_EARLY-NULL},
+  ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}
 };
 EOF
 
 #include "sysdep.h"
 #include "bfd.h"
 #include "bfdlink.h"
+#include "ctf-api.h"
 
 #include "ld.h"
 #include "ldmain.h"
   ${LDEMUL_RECOGNIZED_FILE-NULL},
   ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL},
   ${LDEMUL_NEW_VERS_PATTERN-NULL},
-  ${LDEMUL_EXTRA_MAP_FILE_TEXT-NULL}
+  ${LDEMUL_EXTRA_MAP_FILE_TEXT-NULL},
+  ${LDEMUL_EMIT_CTF_EARLY-NULL},
+  ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}
 };
 EOF
 
 #include "sysdep.h"
 #include "bfd.h"
 #include "bfdlink.h"
+#include "ctf-api.h"
 
 #include "ld.h"
 #include "ldmain.h"
   NULL,        /* recognized file */
   NULL,        /* find_potential_libraries */
   NULL,        /* new_vers_pattern */
-  NULL /* extra_map_file_text */
+  NULL,        /* extra_map_file_text */
+  ${LDEMUL_EMIT_CTF_EARLY-NULL},
+  ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}
 };
 EOF
 
 #include "sysdep.h"
 #include "bfd.h"
 #include "bfdlink.h"
+#include "ctf-api.h"
 
 #include "ld.h"
 #include "getopt.h"
   ${LDEMUL_RECOGNIZED_FILE-NULL},
   ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL},
   ${LDEMUL_NEW_VERS_PATTERN-NULL},
-  ${LDEMUL_EXTRA_MAP_FILE_TEXT-NULL}
+  ${LDEMUL_EXTRA_MAP_FILE_TEXT-NULL},
+  ${LDEMUL_EMIT_CTF_EARLY-NULL},
+  ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}
 };
 EOF
 # \f
 
 #include "sysdep.h"
 #include "bfd.h"
 #include "bfdlink.h"
+#include "ctf-api.h"
 #include "getopt.h"
 #include "libiberty.h"
 #include "filenames.h"
   gld_${EMULATION_NAME}_recognized_file,
   gld_${EMULATION_NAME}_find_potential_libraries,
   NULL,        /* new_vers_pattern.  */
-  NULL /* extra_map_file_text.  */
+  NULL,        /* extra_map_file_text.  */
+  ${LDEMUL_EMIT_CTF_EARLY-NULL},
+  ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}
 };
 EOF
 
 #include "sysdep.h"
 #include "bfd.h"
 #include "bfdlink.h"
+#include "ctf-api.h"
 #include "getopt.h"
 #include "libiberty.h"
 #include "filenames.h"
   gld_${EMULATION_NAME}_recognized_file,
   gld_${EMULATION_NAME}_find_potential_libraries,
   NULL,        /* new_vers_pattern.  */
-  NULL /* extra_map_file_text */
+  NULL,        /* extra_map_file_text */
+  ${LDEMUL_EMIT_CTF_EARLY-NULL},
+  ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}
 };
 EOF
 
 #include "sysdep.h"
 #include "bfd.h"
 #include "bfdlink.h"
+#include "ctf-api.h"
 #include "getopt.h"
 
 #include "ld.h"
   NULL, /* recognized file */
   NULL,        /* find_potential_libraries */
   NULL,        /* new_vers_pattern */
-  NULL  /* extra_map_file_text */
+  NULL,  /* extra_map_file_text */
+  ${LDEMUL_EMIT_CTF_EARLY-NULL},
+  ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}
 };
 EOF
 
 #include "sysdep.h"
 #include "bfd.h"
 #include "bfdlink.h"
+#include "ctf-api.h"
 
 #include "ld.h"
 #include "ldmisc.h"
   NULL,        /* recognized file */
   NULL,        /* find_potential_libraries */
   NULL,        /* new_vers_pattern */
-  NULL /* extra_map_file_text */
+  NULL,        /* extra_map_file_text */
+  NULL, /* emit_ctf_early */
+  NULL  /* examine_strtab_for_ctf */
 };
 EOF
 
 #include "sysdep.h"
 #include "bfd.h"
 #include "bfdlink.h"
+#include "ctf-api.h"
 #include "libiberty.h"
 #include "demangle.h"
 #include "objalloc.h"
 
 #include "bfd.h"
 #include "bfdlink.h"
 #include "safe-ctype.h"
+#include "ctf-api.h"
 
 #include "ld.h"
 #include "ldexp.h"
 
 #include "filenames.h"
 #include "safe-ctype.h"
 #include "bfdlink.h"
+#include "ctf-api.h"
 #include "ld.h"
 #include "ldmain.h"
 #include "ldmisc.h"
 
 #include "sysdep.h"
 #include "bfd.h"
 #include "bfdlink.h"
+#include "ctf-api.h"
 #include "ld.h"
 #include "ldmain.h"
 #include "ldmisc.h"
   if (tries == 0)
     einfo (_("%F%P: looping in map_segments"));
 }
+
+/* We want to emit CTF early if and only if we are not targetting ELF with this
+   invocation.  */
+
+int
+ldelf_emit_ctf_early (void)
+{
+  if (bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour)
+    return 0;
+  return 1;
+}
+
+/* Callbacks used to map from bfd types to libctf types, under libctf's
+   control.  */
+
+struct ctf_strsym_iter_cb_arg
+{
+  struct elf_sym_strtab *syms;
+  bfd_size_type symcount;
+  struct elf_strtab_hash *symstrtab;
+  size_t next_i;
+  size_t next_idx;
+};
+
+/* Return strings from the strtab to libctf, one by one.  Returns NULL when
+   iteration is complete.  */
+
+static const char *
+ldelf_ctf_strtab_iter_cb (uint32_t *offset, void *arg_)
+{
+  bfd_size_type off;
+  const char *ret;
+
+  struct ctf_strsym_iter_cb_arg *arg =
+    (struct ctf_strsym_iter_cb_arg *) arg_;
+
+  /* There is no zeroth string.  */
+  if (arg->next_i == 0)
+    arg->next_i = 1;
+
+  if (arg->next_i >= _bfd_elf_strtab_len (arg->symstrtab))
+    {
+      arg->next_i = 0;
+      return NULL;
+    }
+
+  ret = _bfd_elf_strtab_str (arg->symstrtab, arg->next_i++, &off);
+  *offset = off;
+
+  /* If we've overflowed, we cannot share any further strings: the CTF
+     format cannot encode strings with such high offsets.  */
+  if (*offset != off)
+    return NULL;
+
+  return ret;
+}
+
+/* Return symbols from the symbol table to libctf, one by one.  We assume (and
+   assert) that the symbols in the elf_link_hash_table are in strictly ascending
+   order, and that none will be added in between existing ones.  Returns NULL
+   when iteration is complete.  */
+
+static struct ctf_link_sym *
+ldelf_ctf_symbols_iter_cb (struct ctf_link_sym *dest,
+                                          void *arg_)
+{
+  struct ctf_strsym_iter_cb_arg *arg =
+    (struct ctf_strsym_iter_cb_arg *) arg_;
+
+  if (arg->next_i > arg->symcount)
+    {
+      arg->next_i = 0;
+      arg->next_idx = 0;
+      return NULL;
+    }
+
+  ASSERT (arg->syms[arg->next_i].dest_index == arg->next_idx);
+  dest->st_name = _bfd_elf_strtab_str (arg->symstrtab, arg->next_i, NULL);
+  dest->st_shndx = arg->syms[arg->next_i].sym.st_shndx;
+  dest->st_type = ELF_ST_TYPE (arg->syms[arg->next_i].sym.st_info);
+  dest->st_value = arg->syms[arg->next_i].sym.st_value;
+  arg->next_i++;
+  return dest;
+}
+
+void
+ldelf_examine_strtab_for_ctf
+  (struct ctf_file *ctf_output, struct elf_sym_strtab *syms,
+   bfd_size_type symcount, struct elf_strtab_hash *symstrtab)
+{
+  struct ctf_strsym_iter_cb_arg args = { syms, symcount, symstrtab,
+                                         0, 0 };
+   if (!ctf_output)
+     return;
+
+   if (bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour
+       && !bfd_link_relocatable (&link_info))
+    {
+      if (ctf_link_add_strtab (ctf_output, ldelf_ctf_strtab_iter_cb,
+                              &args) < 0)
+       einfo (_("%F%P: warning: CTF strtab association failed; strings will "
+                "not be shared: %s\n"),
+              ctf_errmsg (ctf_errno (ctf_output)));
+
+      if (ctf_link_shuffle_syms (ctf_output, ldelf_ctf_symbols_iter_cb,
+                                &args) < 0)
+       einfo (_("%F%P: warning: CTF symbol shuffling failed; slight space "
+                "cost: %s\n"), ctf_errmsg (ctf_errno (ctf_output)));
+    }
+}
 
    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
    MA 02110-1301, USA.  */
 
+struct elf_sym_strtab;
+struct elf_strtab_hash;
+struct ctf_file;
+
 extern void ldelf_map_segments (bfd_boolean);
+extern int ldelf_emit_ctf_early (void);
+extern void ldelf_examine_strtab_for_ctf
+  (struct ctf_file *ctf_output, struct elf_sym_strtab *syms,
+   bfd_size_type symcount, struct elf_strtab_hash *symstrtab);
 
 #include "bfd.h"
 #include "getopt.h"
 #include "bfdlink.h"
+#include "ctf-api.h"
 
 #include "ld.h"
 #include "ldmisc.h"
   if (ld_emulation->extra_map_file_text)
     ld_emulation->extra_map_file_text (abfd, info, mapf);
 }
+
+int
+ldemul_emit_ctf_early (void)
+{
+  if (ld_emulation->emit_ctf_early)
+    return ld_emulation->emit_ctf_early ();
+  /* If the emulation doesn't know if it wants to emit CTF early, it is going
+     to do so.  */
+  return 1;
+}
+
+void
+ldemul_examine_strtab_for_ctf (struct ctf_file *ctf_output,
+                              struct elf_sym_strtab *syms,
+                              bfd_size_type symcount,
+                              struct elf_strtab_hash *symstrtab)
+
+{
+  if (ld_emulation->examine_strtab_for_ctf)
+    ld_emulation->examine_strtab_for_ctf (ctf_output, syms,
+                                         symcount, symstrtab);
+}
 
   (struct bfd_elf_version_expr *);
 extern void ldemul_extra_map_file_text
   (bfd *, struct bfd_link_info *, FILE *);
+/* Return 1 if we are emitting CTF early, and 0 if ldemul_examine_strtab_for_ctf
+   will be called by the target.  */
+extern int ldemul_emit_ctf_early
+  (void);
+/* Called from per-target code to examine the strtab and symtab.  */
+extern void ldemul_examine_strtab_for_ctf
+  (struct ctf_file *, struct elf_sym_strtab *, bfd_size_type,
+   struct elf_strtab_hash *);
 
 typedef struct ld_emulation_xfer_struct {
   /* Run before parsing the command line and script file.
   void (*extra_map_file_text)
     (bfd *, struct bfd_link_info *, FILE *);
 
+  /* If this returns true, we emit CTF as early as possible: if false, we emit
+     CTF once the strtab and symtab are laid out.  */
+  int (*emit_ctf_early)
+    (void);
+
+  /* Called to examine the string and symbol table late enough in linking that
+     they are finally laid out.  If emit_ctf_early returns true, this is not
+     called and ldemul_maybe_emit_ctf() emits CTF in 'early' mode: otherwise, it
+     waits until 'late'. (Late mode needs explicit support at per-target link
+     time to get called at all).  If set, called by ld when the examine_strtab
+     bfd_link_callback is invoked by per-target code.  */
+  void (*examine_strtab_for_ctf) (struct ctf_file *, struct elf_sym_strtab *,
+                                 bfd_size_type, struct elf_strtab_hash *);
 } ld_emulation_xfer_type;
 
 typedef enum {
 
 #include "sysdep.h"
 #include "bfd.h"
 #include "bfdlink.h"
+#include "ctf-api.h"
 
 #include "ld.h"
 #include "ldmain.h"
 
 #include "sysdep.h"
 #include "bfd.h"
 #include "bfdlink.h"
+#include "ctf-api.h"
 #include "safe-ctype.h"
 #include "ld.h"
 #include "ldmisc.h"
 
 #include "sysdep.h"
 #include "bfd.h"
 #include "bfdlink.h"
+#include "ctf-api.h"
 #include "ld.h"
 #include "ldexp.h"
 #include "ldver.h"
 
 #include "safe-ctype.h"
 #include "obstack.h"
 #include "bfdlink.h"
+#include "ctf-api.h"
 
 #include "ld.h"
 #include "ldmain.h"
 struct lang_phdr *lang_phdr_list;
 struct lang_nocrossrefs *nocrossref_list;
 struct asneeded_minfo **asneeded_list_tail;
+static ctf_file_t *ctf_output;
 
  /* Functions that traverse the linker script and might evaluate
     DEFINED() need to increment this at the start of the traversal.  */
 
 #define SECTION_NAME_MAP_LENGTH (16)
 
+/* CTF sections smaller than this are not compressed: compression of
+   dictionaries this small doesn't gain much, and this lets consumers mmap the
+   sections directly out of the ELF file and use them with no decompression
+   overhead if they want to.  */
+#define CTF_COMPRESSION_THRESHOLD 4096
+
 void *
 stat_alloc (size_t size)
 {
     einfo ("%F");
 }
 
+/* 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_file_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)
+           einfo (_("%P: warning: CTF section in `%pI' not loaded: "
+                    "its types will be discarded: `%s'\n"), file,
+                    ctf_errmsg (err));
+         continue;
+       }
+
+      /* Prevent the contents of this section from being written, while
+        requiring the section itself to be duplicated in the output.  */
+      /* 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;
+
+      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;
+
+  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_file_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->u.the_ctfa.  */
+      if (ctf_link_add_ctf (ctf_output, file->the_ctf, file->filename) < 0)
+       {
+         einfo (_("%F%P: cannot link with CTF in %pB: %s\n"), file->the_bfd,
+                ctf_errmsg (ctf_errno (ctf_output)));
+         ctf_close (file->the_ctf);
+         file->the_ctf = NULL;
+         continue;
+       }
+    }
+
+  if (ctf_link (ctf_output, CTF_LINK_SHARE_UNCONFLICTED) < 0)
+    {
+      einfo (_("%F%P: 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;
+       }
+    }
+}
+
+/* Let the emulation examine the symbol table and strtab to help it optimize the
+   CTF, if supported.  */
+
+void
+ldlang_ctf_apply_strsym (struct elf_sym_strtab *syms, bfd_size_type symcount,
+                        struct elf_strtab_hash *symstrtab)
+{
+  ldemul_examine_strtab_for_ctf (ctf_output, syms, symcount, symstrtab);
+}
+
+/* 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;
+    }
+
+  /* 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;
+
+      if (!output_sect->contents)
+       {
+         einfo (_("%F%P: 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_file_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);
+}
+
 /* Add the supplied name to the symbol table as an undefined reference.
    This is a two step process as the symbol table doesn't even exist at
    the time the ld command line is processed.  First we put the name
   if (config.map_file != NULL)
     lang_print_asneeded ();
 
+  ldlang_open_ctf ();
+
   bfd_section_already_linked_table_free ();
 
   /* Make sure that we're not mixing architectures.  We call this
        }
     }
 
+  /* Merge together CTF sections.  After this, only the symtab-dependent
+     function and data object sections need adjustment.  */
+  lang_merge_ctf ();
+
+  /* Emit the CTF, iff the emulation doesn't need to do late emission after
+     examining things laid out late, like the strtab.  */
+  lang_write_ctf (0);
+
   /* Copy forward lma regions for output sections in same lma region.  */
   lang_propagate_lma_regions ();
 
 
 
   bfd *the_bfd;
 
+  ctf_archive_t *the_ctf;
+
   struct flag_info *section_flag_list;
 
   /* Next pointer for file_chain statement list.  */
 extern bfd_boolean load_symbols
   (lang_input_statement_type *, lang_statement_list_type *);
 
+struct elf_sym_strtab;
+struct elf_strtab_hash;
+extern void ldlang_ctf_apply_strsym
+  (struct elf_sym_strtab *, bfd_size_type, struct elf_strtab_hash *);
+extern void ldlang_write_ctf_late
+  (void);
 extern bfd_boolean
 ldlang_override_segment_assignment
   (struct bfd_link_info *, bfd *, asection *, asection *, bfd_boolean);
 
 #include "bfd.h"
 #include "safe-ctype.h"
 #include "bfdlink.h"
+#include "ctf-api.h"
 #include "ld.h"
 #include "ldmisc.h"
 #include "ldexp.h"
 
 #include "libiberty.h"
 #include "progress.h"
 #include "bfdlink.h"
+#include "ctf-api.h"
 #include "filenames.h"
 
 #include "ld.h"
   einfo,
   info_msg,
   minfo,
-  ldlang_override_segment_assignment
+  ldlang_override_segment_assignment,
+  ldlang_ctf_apply_strsym,
+  ldlang_write_ctf_late
 };
 
 static bfd_assert_handler_type default_bfd_assert_handler;
 
 #include "bfd.h"
 #include "bfdlink.h"
 #include "libiberty.h"
+#include "ctf-api.h"
 #include "safe-ctype.h"
 #include "filenames.h"
 #include "demangle.h"
 
 #include "bfd.h"
 #include "bfdver.h"
 #include "bfdlink.h"
+#include "ctf-api.h"
 #include "ld.h"
 #include "ldver.h"
 #include "ldexp.h"
 
 #include "bfd.h"
 #include "bfdlink.h"
 #include "libiberty.h"
+#include "ctf-api.h"
 #include "safe-ctype.h"
 
 #include "ld.h"
 
 #include "safe-ctype.h"
 #include "getopt.h"
 #include "bfdlink.h"
+#include "ctf-api.h"
 #include "ld.h"
 #include "ldmain.h"
 #include "ldmisc.h"
 
 #include "sysdep.h"
 #include "bfd.h"
 #include "bfdlink.h"
+#include "ctf-api.h"
 #include "ld.h"
 #include "ldexp.h"
 #include "ldlang.h"
 
 #include "libiberty.h"
 #include "filenames.h"
 #include "safe-ctype.h"
+#include "ctf-api.h"
 
 #include <time.h>
 
 
 #include "bfd.h"
 #include "bfdlink.h"
 #include "bfdver.h"
+#include "ctf-api.h"
 #include "ld.h"
 #include "ldmain.h"
 #include "ldmisc.h"
 
        setup_xfail "mips*-*-irix5*"
     }
 
-    if ![ld_link $CC tmpdir/ld1 "$flags tmpdir/ld-partial.o $BFDLIB $LIBIBERTY $extralibs"] {
+    if ![ld_link $CC tmpdir/ld1 "$flags tmpdir/ld-partial.o $CTFLIB $BFDLIB $LIBIBERTY $extralibs"] {
        fail $testname
        continue
     }
     }
 
     regsub /tmpdir/ld/ $gcc_B_opt_save /tmpdir/gccld1/ gcc_B_opt
-    if ![ld_link $CC tmpdir/ld2 "$flags $OFILES $BFDLIB $LIBIBERTY $extralibs"] {
+    if ![ld_link $CC tmpdir/ld2 "$flags $OFILES $CTFLIB $BFDLIB $LIBIBERTY $extralibs"] {
        fail $testname
        continue
     }
 
     regsub /tmpdir/ld/ $gcc_B_opt_save /tmpdir/gccld2/ gcc_B_opt
-    if ![ld_link $CC tmpdir/ld3 "$flags $OFILES $BFDLIB $LIBIBERTY $extralibs"] {
+    if ![ld_link $CC tmpdir/ld3 "$flags $OFILES $CTFLIB $BFDLIB $LIBIBERTY $extralibs"] {
        fail $testname
        continue
     }
        # generated by different linkers, tmpdir/ld1 and tmpdir/ld2.
        # So we rebuild tmpdir/ld2 with tmpdir/ld3.
        regsub /tmpdir/ld/ $gcc_B_opt_save /tmpdir/gccld3/ gcc_B_opt
-       if ![ld_link $CC tmpdir/ld2 "$flags $OFILES $BFDLIB $LIBIBERTY $extralibs"] {
+       if ![ld_link $CC tmpdir/ld2 "$flags $OFILES $CTFLIB $BFDLIB $LIBIBERTY $extralibs"] {
            fail $testname
            continue
        }