public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v2 10/19] libctf: ELF file opening via BFD
  2019-05-17 22:10 [PATCH v2 00/19] libctf, and CTF support for objdump and readelf Nick Alcock
                   ` (13 preceding siblings ...)
  2019-05-17 22:10 ` [PATCH v2 09/19] libctf: opening Nick Alcock
@ 2019-05-17 22:10 ` Nick Alcock
  2019-05-17 22:10 ` [PATCH v2 02/19] include: new header ctf-api.h Nick Alcock
                   ` (5 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nick Alcock @ 2019-05-17 22:10 UTC (permalink / raw)
  To: binutils

These functions let you open an ELF file with a customarily-named CTF
section in it, automatically opening the CTF file and associating the
symbol and string tables in the ELF file with the CTF container, so that
you can look up the types of symbols in the ELF file via
ctf_lookup_by_symbol(), and so that strings can be shared between the
ELF file and CTF container, to save space.

It uses BFD machinery to do so.  I have no idea if I'm using this
machinery right, and it hasn't been thoroughly tested yet, but it is
better than the manual thrashing that was there before.

We use a forward declaration for the struct bfd in ctf-api.h, so that
ctf-api.h users are not required to pull in <bfd.h>.  (This is mostly
for the sake of readelf.)

These functions have not been tested since their CTF rewrite: this will
happen soon, once we have enough linker machinery together to build ELF files
with all the necessary sections in at once.

Changes from v1:
 - Correct erroneous license (GPLv2+ -> v3+) and reset copyright years.
 - Move out of ctf_lib.c; functions now based on BFD, and located in
   ctf-open-bfd.c.
 - New ctf_bfdopen() to do the low-level opening given a bfd.
 - New ctf_bfdopen_ctfsect() to do the low-level opening given a bfd and
   a separately-specified CTF section (will later be used to open
   archives using a bfd).

libctf/
	* ctf-open-bfd.c: New file.
	* ctf-impl.h: Include bfd.h.
	(ctf_file): New members ctf_abfd, ctf_data_alloced,
	ctf_data_mmapped, ctf_data_mmapped_len, ctf_symtab_alloced,
	ctf_strtab_alloced, ctf_bfd_close.
	(ctf_bfdopen_ctfsect): New declaration.
	(_CTF_SECTION): likewise.

include/
	* ctf-api.h (struct bfd): New forward.
	(ctf_fdopen): New.
	(ctf_bfdopen): Likewise.
	(ctf_open): Likewise.
---
 include/ctf-api.h     |   8 ++
 libctf/ctf-impl.h     |  11 ++
 libctf/ctf-open-bfd.c | 264 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 283 insertions(+)
 create mode 100644 libctf/ctf-open-bfd.c

diff --git a/include/ctf-api.h b/include/ctf-api.h
index c5eb9c676b..4c532f2867 100644
--- a/include/ctf-api.h
+++ b/include/ctf-api.h
@@ -45,6 +45,11 @@ typedef struct ctf_file ctf_file_t;
 typedef struct ctf_archive ctf_archive_t;
 typedef long ctf_id_t;
 
+/* This opaque definition allows libctf to accept BFD data structures without
+   importing all the BFD noise into users' namespaces.  */
+
+struct bfd;
+
 /* If the debugger needs to provide the CTF library with a set of raw buffers
    for use as the CTF data, symbol table, and string table, it can do so by
    filling in ctf_sect_t structures and passing them to ctf_bufopen().
@@ -200,8 +205,11 @@ enum
 
 extern ctf_file_t *ctf_simple_open (const char *, size_t, const char *, size_t,
 				   size_t, const char *, size_t, int *);
+extern ctf_file_t *ctf_bfdopen (struct bfd *, int *);
 extern ctf_file_t *ctf_bufopen (const ctf_sect_t *, const ctf_sect_t *,
 				const ctf_sect_t *, int *);
+extern ctf_file_t *ctf_fdopen (int, const char *, int *);
+extern ctf_file_t *ctf_open (const char *, int *);
 extern ctf_file_t *ctf_create (int *);
 extern void ctf_close (ctf_file_t *);
 extern ctf_sect_t ctf_getdatasect (const ctf_file_t *);
diff --git a/libctf/ctf-impl.h b/libctf/ctf-impl.h
index 53d062745a..3944cfeaee 100644
--- a/libctf/ctf-impl.h
+++ b/libctf/ctf-impl.h
@@ -31,6 +31,7 @@
 #include <limits.h>
 #include <ctype.h>
 #include <elf.h>
+#include <bfd.h>
 
 #ifdef	__cplusplus
 extern "C"
@@ -185,9 +186,15 @@ typedef struct ctf_bundle
 struct ctf_file
 {
   const ctf_fileops_t *ctf_fileops; /* Version-specific file operations.  */
+  bfd *ctf_abfd;		    /* Optional source of section data.  */
   ctf_sect_t ctf_data;		    /* CTF data from object file.  */
   ctf_sect_t ctf_symtab;	    /* Symbol table from object file.  */
   ctf_sect_t ctf_strtab;	    /* String table from object file.  */
+  void *ctf_data_alloced;	    /* CTF data we allocated, to free later.  */
+  void *ctf_data_mmapped;	    /* CTF data we mmapped, to free later.  */
+  size_t ctf_data_mmapped_len;	    /* Length of CTF data we mmapped.  */
+  void *ctf_symtab_alloced;	    /* symtab data we allocated.  */
+  void *ctf_strtab_alloced;	    /* symtab data we allocated.  */
   ctf_hash_t *ctf_structs;	    /* Hash table of struct types.  */
   ctf_hash_t *ctf_unions;	    /* Hash table of union types.  */
   ctf_hash_t *ctf_enums;	    /* Hash table of enum types.  */
@@ -226,6 +233,7 @@ struct ctf_file
   unsigned long ctf_snapshot_lu;  /* ctf_snapshot() call count at last update.  */
   char *ctf_tmp_typeslice;	  /* Storage for slicing up type names.  */
   size_t ctf_tmp_typeslicelen;	  /* Size of the typeslice.  */
+  void (*ctf_bfd_close) (struct ctf_file *); /* Frees BFD bits on close.  */
   void *ctf_specific;		  /* Data for ctf_get/setspecific().  */
 };
 
@@ -311,6 +319,8 @@ extern const char *ctf_strptr (ctf_file_t *, uint32_t);
 
 extern ctf_file_t *ctf_set_open_errno (int *, int);
 extern long ctf_set_errno (ctf_file_t *, int);
+extern ctf_file_t *ctf_bfdopen_ctfsect (struct bfd *, const ctf_sect_t *,
+					int *);
 
 _libctf_malloc_
 extern void *ctf_data_alloc (size_t);
@@ -342,6 +352,7 @@ extern Elf64_Sym *ctf_sym_to_elf64 (const Elf32_Sym *src, Elf64_Sym *dst);
 
 /* Variables, all underscore-prepended. */
 
+extern const char _CTF_SECTION[];	/* name of CTF ELF section */
 extern const char _CTF_NULLSTR[];	/* empty string */
 
 extern int _libctf_debug;	/* debugging messages enabled */
diff --git a/libctf/ctf-open-bfd.c b/libctf/ctf-open-bfd.c
new file mode 100644
index 0000000000..8dee8a35fa
--- /dev/null
+++ b/libctf/ctf-open-bfd.c
@@ -0,0 +1,264 @@
+/* Opening CTF files with BFD.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+
+   This file is part of libctf.
+
+   libctf is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+   See the GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <ctf-impl.h>
+#include <stddef.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <elf.h>
+#include <bfd.h>
+
+#include "elf-bfd.h"
+
+/* Free the BFD bits of a CTF file on ctf_close().  */
+static void
+ctf_bfdclose (ctf_file_t *fp)
+{
+  if (fp->ctf_abfd != NULL)
+    if (!bfd_close_all_done (fp->ctf_abfd))
+      ctf_dprintf ("Cannot close BFD: %s\n", bfd_errmsg (bfd_get_error()));
+}
+
+/* Open a CTF file given the specified BFD.  */
+
+ctf_file_t *
+ctf_bfdopen (struct bfd *abfd, int *errp)
+{
+  ctf_file_t *fp;
+  asection *ctf_asect;
+  bfd_byte *contents;
+  ctf_sect_t ctfsect;
+
+  libctf_init_debug();
+
+  if ((ctf_asect = bfd_get_section_by_name (abfd, _CTF_SECTION)) == NULL)
+    {
+      return (ctf_set_open_errno (errp, ECTF_NOCTFDATA));
+    }
+
+  if (!bfd_malloc_and_get_section (abfd, ctf_asect, &contents))
+    {
+      ctf_dprintf ("ctf_bfdopen(): cannot malloc CTF section: %s\n",
+		   bfd_errmsg (bfd_get_error()));
+      return (ctf_set_open_errno (errp, ECTF_FMT));
+    }
+
+  ctfsect.cts_name = _CTF_SECTION;
+  ctfsect.cts_type = SHT_PROGBITS;
+  ctfsect.cts_flags = 0;
+  ctfsect.cts_entsize = 1;
+  ctfsect.cts_offset = 0;
+  ctfsect.cts_size = bfd_section_size (abfd, ctf_asect);
+  ctfsect.cts_data = contents;
+
+  if ((fp = ctf_bfdopen_ctfsect (abfd, &ctfsect, errp)) != NULL)
+    {
+      fp->ctf_data_alloced = (void *) ctfsect.cts_data;
+      return fp;
+    }
+
+  free (contents);
+  return NULL;					/* errno is set for us.  */
+}
+
+/* Open a CTF file given the specified BFD and CTF section.  */
+
+ctf_file_t *
+ctf_bfdopen_ctfsect (struct bfd *abfd, const ctf_sect_t *ctfsect, int *errp)
+{
+  ctf_file_t *fp;
+  ctf_sect_t *symsectp = NULL;
+  ctf_sect_t *strsectp = NULL;
+  const char *bfderrstr = NULL;
+
+  asection *sym_asect;
+  ctf_sect_t symsect, strsect;
+  /* TODO: handle SYMTAB_SHNDX.  */
+
+  if ((sym_asect = bfd_section_from_elf_index (abfd,
+					       elf_onesymtab (abfd))) != NULL)
+    {
+      Elf_Internal_Shdr *symhdr = &elf_symtab_hdr (abfd);
+      asection *str_asect = NULL;
+      bfd_byte *contents;
+
+      if (symhdr->sh_link != SHN_UNDEF &&
+	  symhdr->sh_link <= elf_numsections (abfd))
+	str_asect = bfd_section_from_elf_index (abfd, symhdr->sh_link);
+
+      Elf_Internal_Shdr *strhdr = elf_elfsections (abfd)[symhdr->sh_link];
+
+      if (sym_asect && str_asect)
+	{
+	  if (!bfd_malloc_and_get_section (abfd, str_asect, &contents))
+	    {
+	      bfderrstr = "Cannot malloc string table";
+	      free (contents);
+	      goto err;
+	    }
+	  strsect.cts_data = contents;
+	  strsect.cts_name = (char *) strsect.cts_data + strhdr->sh_name;
+	  strsect.cts_type = strhdr->sh_type;
+	  strsect.cts_flags = strhdr->sh_flags;
+	  strsect.cts_entsize = strhdr->sh_size;
+	  strsect.cts_offset = strhdr->sh_offset;
+	  strsectp = &strsect;
+
+	  if (!bfd_malloc_and_get_section (abfd, sym_asect, &contents))
+	    {
+	      bfderrstr = "Cannot malloc symbol table";
+	      free (contents);
+	      goto err_free_str;
+	    }
+
+	  symsect.cts_name = (char *) strsect.cts_data + symhdr->sh_name;
+	  symsect.cts_type = symhdr->sh_type;
+	  symsect.cts_flags = symhdr->sh_flags;
+	  symsect.cts_entsize = symhdr->sh_size;
+	  symsect.cts_data = contents;
+	  symsect.cts_offset = symhdr->sh_offset;
+	  symsectp = &symsect;
+	}
+    }
+
+  if ((fp = ctf_bufopen (ctfsect, symsectp, strsectp, errp)) != NULL)
+    {
+      if (symsectp)
+	fp->ctf_symtab_alloced = (void *) symsectp->cts_data;
+      if (strsectp)
+	fp->ctf_strtab_alloced = (void *) strsectp->cts_data;
+      fp->ctf_bfd_close = ctf_bfdclose;
+      return fp;
+    }
+  ctf_dprintf ("ctf_internal_open(): cannot open CTF: %s\n",
+	       ctf_errmsg (*errp));
+
+err_free_str:
+  free ((void *) strsect.cts_data);
+err: _libctf_unused_;
+  if (bfderrstr)
+    {
+      ctf_dprintf ("ctf_bfdopen(): %s: %s\n", bfderrstr,
+		   bfd_errmsg (bfd_get_error()));
+      ctf_set_open_errno (errp, ECTF_FMT);
+    }
+  return NULL;
+}
+
+
+/* Open the specified file descriptor and return a pointer to a CTF container.
+   The file can be either an ELF file or raw CTF file.  The caller is
+   responsible for closing the file descriptor when it is no longer needed.
+
+   TODO: handle CTF archives too.  */
+
+ctf_file_t *
+ctf_fdopen (int fd, const char *filename, int *errp)
+{
+  ctf_file_t *fp = NULL;
+  bfd *abfd;
+  int nfd;
+
+  struct stat st;
+  ssize_t nbytes;
+
+  ctf_preamble_t ctfhdr;
+
+  memset (&ctfhdr, 0, sizeof (ctfhdr));
+
+  libctf_init_debug();
+
+  if (fstat (fd, &st) == -1)
+    return (ctf_set_open_errno (errp, errno));
+
+  if ((nbytes = ctf_pread (fd, &ctfhdr, sizeof (ctfhdr), 0)) <= 0)
+    return (ctf_set_open_errno (errp, nbytes < 0 ? errno : ECTF_FMT));
+
+  /* If we have read enough bytes to form a CTF header and the magic
+     string matches, attempt to interpret the file as raw CTF.  */
+
+  if ((size_t) nbytes >= sizeof (ctf_preamble_t) &&
+      ctfhdr.ctp_magic == CTF_MAGIC)
+    {
+      void *data;
+
+      if (ctfhdr.ctp_version > CTF_VERSION)
+	return (ctf_set_open_errno (errp, ECTF_CTFVERS));
+
+      if ((data = ctf_mmap (st.st_size, 0, fd)) == NULL)
+	return (ctf_set_open_errno (errp, errno));
+
+      if ((fp = ctf_simple_open (data, (size_t) st.st_size, NULL, 0, 0,
+				 NULL, 0, errp)) == NULL)
+	ctf_munmap (data, (size_t) st.st_size);
+      fp->ctf_data_mmapped = data;
+      fp->ctf_data_mmapped_len = (size_t) st.st_size;
+
+      return fp;
+    }
+
+  /* Attempt to open the file with BFD.  We must dup the fd first, since bfd
+     takes ownership of the passed fd.  */
+
+  if ((nfd = dup (fd)) < 0)
+      return (ctf_set_open_errno (errp, errno));
+
+  if ((abfd = bfd_fdopenr (filename, NULL, nfd)) == NULL)
+    {
+      ctf_dprintf ("Cannot open BFD from %s: %s\n",
+		   filename ? filename : "(unknown file)",
+		   bfd_errmsg (bfd_get_error()));
+      return (ctf_set_open_errno (errp, ECTF_FMT));
+    }
+
+  if ((fp = ctf_bfdopen (abfd, errp)) == NULL)
+    {
+      if (!bfd_close_all_done (abfd))
+	ctf_dprintf ("Cannot close BFD: %s\n", bfd_errmsg (bfd_get_error()));
+      return NULL;			/* errno is set for us.  */
+    }
+  fp->ctf_abfd = abfd;
+
+  return fp;
+}
+
+/* Open the specified file and return a pointer to a CTF container.  The file
+   can be either an ELF file or raw CTF file.  This is just a convenient
+   wrapper around ctf_fdopen() for callers.  */
+
+ctf_file_t *
+ctf_open (const char *filename, int *errp)
+{
+  ctf_file_t *fp;
+  int fd;
+
+  if ((fd = open (filename, O_RDONLY)) == -1)
+    {
+      if (errp != NULL)
+	*errp = errno;
+      return NULL;
+    }
+
+  fp = ctf_fdopen (fd, filename, errp);
+  (void) close (fd);
+  return fp;
+}
-- 
2.21.0.237.gd0cfaa883d

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v2 02/19] include: new header ctf-api.h
  2019-05-17 22:10 [PATCH v2 00/19] libctf, and CTF support for objdump and readelf Nick Alcock
                   ` (14 preceding siblings ...)
  2019-05-17 22:10 ` [PATCH v2 10/19] libctf: ELF file opening via BFD Nick Alcock
@ 2019-05-17 22:10 ` Nick Alcock
  2019-05-17 22:11 ` [PATCH v2 18/19] libctf: build system Nick Alcock
                   ` (4 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nick Alcock @ 2019-05-17 22:10 UTC (permalink / raw)
  To: binutils

This non-installed header is the means by which libctf consumers
communicate with libctf.

This header will be extended in subsequent commits.

Changes from v1:
 - Correct erroneous license (GPLv2+ -> v3+) and reset copyright years.
 - Flip a bunch of errors no longer generatable nor used by any callers
   currently in existence to ECTF_UNUSED*, allowing their reuse later.

include/
	* ctf-api.h: New file.
---
 include/ctf-api.h | 130 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 130 insertions(+)
 create mode 100644 include/ctf-api.h

diff --git a/include/ctf-api.h b/include/ctf-api.h
new file mode 100644
index 0000000000..f2f7ce1b43
--- /dev/null
+++ b/include/ctf-api.h
@@ -0,0 +1,130 @@
+/* Public API to libctf.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+
+   This file is part of libctf.
+
+   libctf is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+   See the GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This header file defines the interfaces available from the CTF debugger
+   library, libctf.  This API can be used by a debugger to operate on data in
+   the Compact ANSI-C Type Format (CTF).  */
+
+#ifndef	_CTF_API_H
+#define	_CTF_API_H
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <ctf.h>
+
+#ifdef	__cplusplus
+extern "C"
+  {
+#endif
+
+/* Clients can open one or more CTF containers and obtain a pointer to an
+   opaque ctf_file_t.  Types are identified by an opaque ctf_id_t token.
+   They can also open or create read-only archives of CTF containers in a
+   ctf_archive_t.
+
+   These opaque definitions allow libctf to evolve without breaking clients.  */
+
+typedef struct ctf_file ctf_file_t;
+typedef struct ctf_archive ctf_archive_t;
+typedef long ctf_id_t;
+
+/* Functions that return integer status or a ctf_id_t use the following value
+   to indicate failure.  ctf_errno() can be used to obtain an error code.  */
+#define	CTF_ERR	(-1L)
+
+#define	ECTF_BASE	1000	/* Base value for libctf errnos.  */
+
+
+enum
+  {
+   ECTF_FMT = ECTF_BASE,	/* File is not in CTF or ELF format.  */
+   ECTF_BFDERR,			/* BFD error.  */
+   ECTF_CTFVERS,		/* CTF version is more recent than libctf.  */
+   ECTF_UNUSED1,		/* Unused error.  */
+   ECTF_SYMTAB,			/* Symbol table uses invalid entry size.  */
+   ECTF_SYMBAD,			/* Symbol table data buffer invalid.  */
+   ECTF_STRBAD,			/* String table data buffer invalid.  */
+   ECTF_CORRUPT,		/* File data corruption detected.  */
+   ECTF_NOCTFDATA,		/* ELF file does not contain CTF data.  */
+   ECTF_NOCTFBUF,		/* Buffer does not contain CTF data.  */
+   ECTF_NOSYMTAB,		/* Symbol table data is not available.  */
+   ECTF_NOPARENT,		/* Parent CTF container is not available.  */
+   ECTF_DMODEL,			/* Data model mismatch.  */
+   ECTF_UNUSED2,		/* Unused error.  */
+   ECTF_ZALLOC,			/* Failed to allocate (de)compression buffer.  */
+   ECTF_DECOMPRESS,		/* Failed to decompress CTF data.  */
+   ECTF_STRTAB,			/* String table for this string is missing.  */
+   ECTF_BADNAME,		/* String offset is corrupt w.r.t. strtab.  */
+   ECTF_BADID,			/* Invalid type ID number.  */
+   ECTF_NOTSOU,			/* Type is not a struct or union.  */
+   ECTF_NOTENUM,		/* Type is not an enum.  */
+   ECTF_NOTSUE,			/* Type is not a struct, union, or enum.  */
+   ECTF_NOTINTFP,		/* Type is not an integer, float, or enum.  */
+   ECTF_NOTARRAY,		/* Type is not an array.  */
+   ECTF_NOTREF,			/* Type does not reference another type.  */
+   ECTF_NAMELEN,		/* Buffer is too small to hold type name.  */
+   ECTF_NOTYPE,			/* No type found corresponding to name.  */
+   ECTF_SYNTAX,			/* Syntax error in type name.  */
+   ECTF_NOTFUNC,		/* Symtab entry does not refer to a function.  */
+   ECTF_NOFUNCDAT,		/* No func info available for function.  */
+   ECTF_NOTDATA,		/* Symtab entry does not refer to a data obj.  */
+   ECTF_NOTYPEDAT,		/* No type info available for object.  */
+   ECTF_NOLABEL,		/* No label found corresponding to name.  */
+   ECTF_NOLABELDATA,		/* File does not contain any labels.  */
+   ECTF_NOTSUP,			/* Feature not supported.  */
+   ECTF_NOENUMNAM,		/* Enum element name not found.  */
+   ECTF_NOMEMBNAM,		/* Member name not found.  */
+   ECTF_RDONLY,			/* CTF container is read-only.  */
+   ECTF_DTFULL,			/* CTF type is full (no more members allowed).  */
+   ECTF_FULL,			/* CTF container is full.  */
+   ECTF_DUPLICATE,		/* Duplicate member or variable name.  */
+   ECTF_CONFLICT,		/* Conflicting type definition present.  */
+   ECTF_OVERROLLBACK,		/* Attempt to roll back past a ctf_update.  */
+   ECTF_COMPRESS,		/* Failed to compress CTF data.  */
+   ECTF_ARCREATE,		/* Error creating CTF archive.  */
+   ECTF_ARNNAME,		/* Name not found in CTF archive.  */
+   ECTF_SLICEOVERFLOW,		/* Overflow of type bitness or offset in slice.  */
+   ECTF_DUMPSECTUNKNOWN,	/* Unknown section number in dump.  */
+   ECTF_DUMPSECTCHANGED		/* Section changed in middle of dump.  */
+  };
+
+/* The CTF data model is inferred to be the caller's data model or the data
+   model of the given object, unless ctf_setmodel() is explicitly called.  */
+#define	CTF_MODEL_ILP32 1	/* Object data model is ILP32.  */
+#define	CTF_MODEL_LP64  2	/* Object data model is LP64.  */
+#ifdef _LP64
+# define CTF_MODEL_NATIVE CTF_MODEL_LP64
+#else
+# define CTF_MODEL_NATIVE CTF_MODEL_ILP32
+#endif
+
+/* Dynamic CTF containers can be created using ctf_create().  The ctf_add_*
+   routines can be used to add new definitions to the dynamic container.
+   New types are labeled as root or non-root to determine whether they are
+   visible at the top-level program scope when subsequently doing a lookup.  */
+
+#define	CTF_ADD_NONROOT	0	/* Type only visible in nested scope.  */
+#define	CTF_ADD_ROOT	1	/* Type visible at top-level scope.  */
+
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif				/* _CTF_API_H */
-- 
2.21.0.237.gd0cfaa883d

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v2 04/19] libctf: low-level list manipulation and helper utilities
  2019-05-17 22:10 [PATCH v2 00/19] libctf, and CTF support for objdump and readelf Nick Alcock
                   ` (10 preceding siblings ...)
  2019-05-17 22:10 ` [PATCH v2 08/19] libctf: creation functions Nick Alcock
@ 2019-05-17 22:10 ` Nick Alcock
  2019-05-17 22:10 ` [PATCH v2 13/19] libctf: type copying Nick Alcock
                   ` (8 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nick Alcock @ 2019-05-17 22:10 UTC (permalink / raw)
  To: binutils

These utilities are a bit of a ragbag of small things needed by more
than one TU: list manipulation, ELF32->64 translators, routines to look
up strings in string tables, dynamically-allocated string appenders, and
routines to set the specialized errno values previously committed in
<ctf-api.h>.

We do still need to dig around in raw ELF symbol tables in places,
because libctf allows the caller to pass in the contents of string and
symbol sections without telling it where they come from, so we cannot
use BFD to get the symbols (BFD reasonably demands the entire file).  So
extract minimal ELF definitions from glibc into a private header named
libctf/elf.h: later, we use those to get symbols.  (The start-of-
copyright range on elf.h reflects this glibc heritage.)

Changes from v1:
 - Correct erroneous license (GPLv2+ -> v3+) and reset copyright years.
 - Use elf.h, not gelf.h; migrate away from gelf types
 - Mark some functions with _libctf_malloc_
 - No longer use C++ reserved words as identifiers in the list handling
   code

libctf/
	* ctf-util.c: New file.
	* elf.h: Likewise.
	* ctf-impl.h: Include it, and add declarations.
---
 libctf/ctf-impl.h |  33 +++++++++
 libctf/ctf-util.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++
 libctf/elf.h      |  61 ++++++++++++++++
 3 files changed, 270 insertions(+)
 create mode 100644 libctf/ctf-util.c
 create mode 100644 libctf/elf.h

diff --git a/libctf/ctf-impl.h b/libctf/ctf-impl.h
index 4356a2a9f0..ca5397f9c7 100644
--- a/libctf/ctf-impl.h
+++ b/libctf/ctf-impl.h
@@ -24,6 +24,13 @@
 #include <sys/errno.h>
 #include <ctf-api.h>
 #include <sys/types.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <limits.h>
+#include <ctype.h>
+#include <elf.h>
 
 #ifdef	__cplusplus
 extern "C"
@@ -51,6 +58,25 @@ extern "C"
 
 #endif
 
+typedef struct ctf_list
+{
+  struct ctf_list *l_prev;	/* Previous pointer or tail pointer.  */
+  struct ctf_list *l_next;	/* Next pointer or head pointer.  */
+} ctf_list_t;
+
+#define	ctf_list_prev(elem)	((void *)(((ctf_list_t *)(elem))->l_prev))
+#define	ctf_list_next(elem)	((void *)(((ctf_list_t *)(elem))->l_next))
+
+extern void ctf_list_append (ctf_list_t *, void *);
+extern void ctf_list_prepend (ctf_list_t *, void *);
+extern void ctf_list_delete (ctf_list_t *, void *);
+
+extern const char *ctf_strraw (ctf_file_t *, uint32_t);
+extern const char *ctf_strptr (ctf_file_t *, uint32_t);
+
+extern ctf_file_t *ctf_set_open_errno (int *, int);
+extern long ctf_set_errno (ctf_file_t *, int);
+
 _libctf_malloc_
 extern void *ctf_data_alloc (size_t);
 extern void ctf_data_free (void *, size_t);
@@ -65,10 +91,17 @@ _libctf_malloc_
 extern void *ctf_alloc (size_t);
 extern void ctf_free (void *);
 
+_libctf_malloc_
+extern char *ctf_strdup (const char *);
+extern char *ctf_str_append (char *, const char *);
+extern const char *ctf_strerror (int);
+
 _libctf_printflike_ (1, 2)
 extern void ctf_dprintf (const char *, ...);
 extern void libctf_init_debug (void);
 
+extern Elf64_Sym *ctf_sym_to_elf64 (const Elf32_Sym *src, Elf64_Sym *dst);
+
 extern int _libctf_debug;	/* debugging messages enabled */
 
 #ifdef	__cplusplus
diff --git a/libctf/ctf-util.c b/libctf/ctf-util.c
new file mode 100644
index 0000000000..04d1673481
--- /dev/null
+++ b/libctf/ctf-util.c
@@ -0,0 +1,176 @@
+/* Miscellaneous utilities.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+
+   This file is part of libctf.
+
+   libctf is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+   See the GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <ctf-impl.h>
+#include <string.h>
+
+/* Simple doubly-linked list append routine.  This implementation assumes that
+   each list element contains an embedded ctf_list_t as the first member.
+   An additional ctf_list_t is used to store the head (l_next) and tail
+   (l_prev) pointers.  The current head and tail list elements have their
+   previous and next pointers set to NULL, respectively.  */
+
+void
+ctf_list_append (ctf_list_t *lp, void *newp)
+{
+  ctf_list_t *p = lp->l_prev;	/* p = tail list element.  */
+  ctf_list_t *q = newp;		/* q = new list element.  */
+
+  lp->l_prev = q;
+  q->l_prev = p;
+  q->l_next = NULL;
+
+  if (p != NULL)
+    p->l_next = q;
+  else
+    lp->l_next = q;
+}
+
+/* Prepend the specified existing element to the given ctf_list_t.  The
+   existing pointer should be pointing at a struct with embedded ctf_list_t.  */
+
+void
+ctf_list_prepend (ctf_list_t * lp, void *newp)
+{
+  ctf_list_t *p = newp;		/* p = new list element.  */
+  ctf_list_t *q = lp->l_next;	/* q = head list element.  */
+
+  lp->l_next = p;
+  p->l_prev = NULL;
+  p->l_next = q;
+
+  if (q != NULL)
+    q->l_prev = p;
+  else
+    lp->l_prev = p;
+}
+
+/* Delete the specified existing element from the given ctf_list_t.  The
+   existing pointer should be pointing at a struct with embedded ctf_list_t.  */
+
+void
+ctf_list_delete (ctf_list_t *lp, void *existing)
+{
+  ctf_list_t *p = existing;
+
+  if (p->l_prev != NULL)
+    p->l_prev->l_next = p->l_next;
+  else
+    lp->l_next = p->l_next;
+
+  if (p->l_next != NULL)
+    p->l_next->l_prev = p->l_prev;
+  else
+    lp->l_prev = p->l_prev;
+}
+
+/* Convert a 32-bit ELF symbol into Elf64 and return a pointer to it.  */
+
+Elf64_Sym *
+ctf_sym_to_elf64 (const Elf32_Sym *src, Elf64_Sym *dst)
+{
+  dst->st_name = src->st_name;
+  dst->st_value = src->st_value;
+  dst->st_size = src->st_size;
+  dst->st_info = src->st_info;
+  dst->st_other = src->st_other;
+  dst->st_shndx = src->st_shndx;
+
+  return dst;
+}
+
+/* Convert an encoded CTF string name into a pointer to a C string by looking
+  up the appropriate string table buffer and then adding the offset.  */
+
+const char *
+ctf_strraw (ctf_file_t *fp, uint32_t name)
+{
+  ctf_strs_t *ctsp = &fp->ctf_str[CTF_NAME_STID (name)];
+
+  if (ctsp->cts_strs != NULL && CTF_NAME_OFFSET (name) < ctsp->cts_len)
+    return (ctsp->cts_strs + CTF_NAME_OFFSET (name));
+
+  /* String table not loaded or corrupt offset.  */
+  return NULL;
+}
+
+const char *
+ctf_strptr (ctf_file_t *fp, uint32_t name)
+{
+  const char *s = ctf_strraw (fp, name);
+  return (s != NULL ? s : "(?)");
+}
+
+/* Same as strdup(3C), but use ctf_alloc() to do the memory allocation. */
+
+_libctf_malloc_ char *
+ctf_strdup (const char *s1)
+{
+  char *s2 = ctf_alloc (strlen (s1) + 1);
+
+  if (s2 != NULL)
+    (void) strcpy (s2, s1);
+
+  return s2;
+}
+
+/* A string appender working on dynamic strings.  */
+
+char *
+ctf_str_append (char *s, const char *append)
+{
+  size_t s_len = 0;
+
+  if (append == NULL)
+    return s;
+
+  if (s != NULL)
+    s_len = strlen (s);
+
+  size_t append_len = strlen (append);
+
+  if ((s = realloc (s, s_len + append_len + 1)) == NULL)
+    return NULL;
+
+  memcpy (s + s_len, append, append_len);
+  s[s_len + append_len] = '\0';
+
+  return s;
+}
+
+/* Store the specified error code into errp if it is non-NULL, and then
+   return NULL for the benefit of the caller.  */
+
+ctf_file_t *
+ctf_set_open_errno (int *errp, int error)
+{
+  if (errp != NULL)
+    *errp = error;
+  return NULL;
+}
+
+/* Store the specified error code into the CTF container, and then return
+   CTF_ERR for the benefit of the caller. */
+
+long
+ctf_set_errno (ctf_file_t * fp, int err)
+{
+  fp->ctf_errno = err;
+  return CTF_ERR;
+}
diff --git a/libctf/elf.h b/libctf/elf.h
new file mode 100644
index 0000000000..fee1630909
--- /dev/null
+++ b/libctf/elf.h
@@ -0,0 +1,61 @@
+/* This file defines standard ELF types, structures, and macros.
+   Copyright (C) 1995-2019 Free Software Foundation, Inc.
+
+   This file is part of libctf.
+
+   libctf is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+   See the GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _CTF_ELF_H
+#define _CTF_ELF_H
+
+#include "config.h"
+#include "ansidecl.h"
+#include <stdint.h>
+#include "elf/common.h"
+#include "elf/external.h"
+
+typedef uint32_t Elf32_Word;
+typedef uint32_t Elf64_Word;
+typedef uint32_t Elf32_Addr;
+typedef uint64_t Elf64_Addr;
+typedef uint64_t Elf64_Xword;
+typedef uint16_t Elf32_Section;
+typedef uint16_t Elf64_Section;
+
+#define SHN_EXTABS	0xFFF1		/* Associated symbol is absolute */
+
+/* Symbol table entry.  */
+
+typedef struct
+{
+  Elf32_Word	st_name;		/* Symbol name (string tbl index) */
+  Elf32_Addr	st_value;		/* Symbol value */
+  Elf32_Word	st_size;		/* Symbol size */
+  unsigned char	st_info;		/* Symbol type and binding */
+  unsigned char	st_other;		/* Symbol visibility */
+  Elf32_Section	st_shndx;		/* Section index */
+} Elf32_Sym;
+
+typedef struct
+{
+  Elf64_Word	st_name;		/* Symbol name (string tbl index) */
+  unsigned char	st_info;		/* Symbol type and binding */
+  unsigned char st_other;		/* Symbol visibility */
+  Elf64_Section	st_shndx;		/* Section index */
+  Elf64_Addr	st_value;		/* Symbol value */
+  Elf64_Xword	st_size;		/* Symbol size */
+} Elf64_Sym;
+
+#endif	/* _CTF_ELF_H */
-- 
2.21.0.237.gd0cfaa883d

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v2 08/19] libctf: creation functions
  2019-05-17 22:10 [PATCH v2 00/19] libctf, and CTF support for objdump and readelf Nick Alcock
                   ` (9 preceding siblings ...)
  2019-05-17 22:10 ` [PATCH v2 14/19] libctf: library version enforcement Nick Alcock
@ 2019-05-17 22:10 ` Nick Alcock
  2019-05-29 14:09   ` Szabolcs Nagy
  2019-05-17 22:10 ` [PATCH v2 04/19] libctf: low-level list manipulation and helper utilities Nick Alcock
                   ` (9 subsequent siblings)
  20 siblings, 1 reply; 31+ messages in thread
From: Nick Alcock @ 2019-05-17 22:10 UTC (permalink / raw)
  To: binutils

The CTF creation process looks roughly like (error handling elided):

int err;
ctf_file_t *foo = ctf_create (&err);

ctf_id_t type = ctf_add_THING (foo, ...);
ctf_update (foo);
ctf_*write (...);

Some ctf_add_THING functions accept other type IDs as arguments,
depending on the type: cv-quals, pointers, and structure and union
members all take other types as arguments.  So do 'slices', which
let you take an existing integral type and recast it as a type
with a different bitness or offset within a byte, for bitfields.
One class of THING is not a type: "variables", which are mappings
of names (in the internal string table) to types.  These are mostly
useful when encoding variables that do not appear in a symbol table
but which some external user has some other way to figure out the
address of at runtime (dynamic symbol lookup or querying a VM
interpreter or something).

You can snapshot the creation process at any point: rolling back to a
snapshot deletes all types and variables added since that point.

You can make arbitrary type queries on the CTF container during the
creation process, but you must call ctf_update() first, which
translates the growing dynamic container into a static one (this uses
the CTF opening machinery, added in a later commit), which is quite
expensive.  This function must also be called after adding types
and before writing the container out.

Because addition of types involves looking up existing types, we add a
little of the type lookup machinery here, as well: only enough to
look up types in dynamic containers under construction.

Changes from v1:
 - Correct erroneous license (GPLv2+ -> v3+) and reset copyright years.
 - Move ctf_write(), ctf_gzwrite() and ctf_compress_write() to
   ctf-create.c, since ctf-lib.c is gone
 - drop <gelf.h> and direct mmap usage; use libctf_init_debug(); adjust
   to ctf_free() prototype change.

libctf/
	* ctf-create.c: New file.
	* ctf-lookup.c: New file.

include/
	* ctf-api.h (zlib.h): New include.
	(ctf_sect_t): New.
	(ctf_sect_names_t): Likewise.
	(ctf_encoding_t): Likewise.
	(ctf_membinfo_t): Likewise.
	(ctf_arinfo_t): Likewise.
	(ctf_funcinfo_t): Likewise.
	(ctf_lblinfo_t): Likewise.
	(ctf_snapshot_id_t): Likewise.
	(CTF_FUNC_VARARG): Likewise.
	(ctf_simple_open): Likewise.
	(ctf_bufopen): Likewise.
	(ctf_create): Likewise.
	(ctf_add_array): Likewise.
	(ctf_add_const): Likewise.
	(ctf_add_enum_encoded): Likewise.
	(ctf_add_enum): Likewise.
	(ctf_add_float): Likewise.
	(ctf_add_forward): Likewise.
	(ctf_add_function): Likewise.
	(ctf_add_integer): Likewise.
	(ctf_add_slice): Likewise.
	(ctf_add_pointer): Likewise.
	(ctf_add_type): Likewise.
	(ctf_add_typedef): Likewise.
	(ctf_add_restrict): Likewise.
	(ctf_add_struct): Likewise.
	(ctf_add_union): Likewise.
	(ctf_add_struct_sized): Likewise.
	(ctf_add_union_sized): Likewise.
	(ctf_add_volatile): Likewise.
	(ctf_add_enumerator): Likewise.
	(ctf_add_member): Likewise.
	(ctf_add_member_offset): Likewise.
	(ctf_add_member_encoded): Likewise.
	(ctf_add_variable): Likewise.
	(ctf_set_array): Likewise.
	(ctf_update): Likewise.
	(ctf_snapshot): Likewise.
	(ctf_rollback): Likewise.
	(ctf_discard): Likewise.
	(ctf_write): Likewise.
	(ctf_gzwrite): Likewise.
	(ctf_compress_write): Likewise.
---
 include/ctf-api.h   |  129 ++++
 libctf/ctf-create.c | 1547 +++++++++++++++++++++++++++++++++++++++++++
 libctf/ctf-lookup.c |   63 ++
 3 files changed, 1739 insertions(+)
 create mode 100644 libctf/ctf-create.c
 create mode 100644 libctf/ctf-lookup.c

diff --git a/include/ctf-api.h b/include/ctf-api.h
index 81ec5c6522..030770649e 100644
--- a/include/ctf-api.h
+++ b/include/ctf-api.h
@@ -27,6 +27,7 @@
 #include <sys/param.h>
 #include <sys/types.h>
 #include <ctf.h>
+#include <zlib.h>
 
 #ifdef	__cplusplus
 extern "C"
@@ -44,6 +45,81 @@ typedef struct ctf_file ctf_file_t;
 typedef struct ctf_archive ctf_archive_t;
 typedef long ctf_id_t;
 
+/* If the debugger needs to provide the CTF library with a set of raw buffers
+   for use as the CTF data, symbol table, and string table, it can do so by
+   filling in ctf_sect_t structures and passing them to ctf_bufopen().
+
+   The contents of this structure must always be in native endianness (no
+   byteswapping is performed).  */
+
+typedef struct ctf_sect
+{
+  const char *cts_name;		  /* Section name (if any).  */
+  unsigned long cts_type;	  /* Section type (ELF SHT_... value).  */
+  unsigned long cts_flags;	  /* Section flags (ELF SHF_... value).  */
+  const void *cts_data;		  /* Pointer to section data.  */
+  size_t cts_size;		  /* Size of data in bytes.  */
+  size_t cts_entsize;		  /* Size of each section entry (symtab only).  */
+  off64_t cts_offset;		  /* File offset of this section (if any).  */
+} ctf_sect_t;
+
+/* Symbolic names for CTF sections.  */
+
+typedef enum ctf_sect_names
+  {
+   CTF_SECT_HEADER,
+   CTF_SECT_LABEL,
+   CTF_SECT_OBJT,
+   CTF_SECT_FUNC,
+   CTF_SECT_VAR,
+   CTF_SECT_TYPE,
+   CTF_SECT_STR
+  } ctf_sect_names_t;
+
+/* Encoding information for integers, floating-point values, and certain other
+   intrinsics can be obtained by calling ctf_type_encoding(), below.  The flags
+   field will contain values appropriate for the type defined in <ctf.h>.  */
+
+typedef struct ctf_encoding
+{
+  uint32_t cte_format;		 /* Data format (CTF_INT_* or CTF_FP_* flags).  */
+  uint32_t cte_offset;		 /* Offset of value in bits.  */
+  uint32_t cte_bits;		 /* Size of storage in bits.  */
+} ctf_encoding_t;
+
+typedef struct ctf_membinfo
+{
+  ctf_id_t ctm_type;		/* Type of struct or union member.  */
+  unsigned long ctm_offset;	/* Offset of member in bits.  */
+} ctf_membinfo_t;
+
+typedef struct ctf_arinfo
+{
+  ctf_id_t ctr_contents;	/* Type of array contents.  */
+  ctf_id_t ctr_index;		/* Type of array index.  */
+  uint32_t ctr_nelems;		/* Number of elements.  */
+} ctf_arinfo_t;
+
+typedef struct ctf_funcinfo
+{
+  ctf_id_t ctc_return;		/* Function return type.  */
+  uint32_t ctc_argc;		/* Number of typed arguments to function.  */
+  uint32_t ctc_flags;		/* Function attributes (see below).  */
+} ctf_funcinfo_t;
+
+typedef struct ctf_lblinfo
+{
+  ctf_id_t ctb_type;		/* Last type associated with the label.  */
+} ctf_lblinfo_t;
+
+typedef struct ctf_snapshot_id
+{
+  unsigned long dtd_id;		/* Highest DTD ID at time of snapshot.  */
+  unsigned long snapshot_id;	/* Snapshot id at time of snapshot.  */
+} ctf_snapshot_id_t;
+
+#define	CTF_FUNC_VARARG	0x1	/* Function arguments end with varargs.  */
+
 /* Functions that return integer status or a ctf_id_t use the following value
    to indicate failure.  ctf_errno() can be used to obtain an error code.  */
 #define	CTF_ERR	(-1L)
@@ -122,8 +198,61 @@ enum
 #define	CTF_ADD_NONROOT	0	/* Type only visible in nested scope.  */
 #define	CTF_ADD_ROOT	1	/* Type visible at top-level scope.  */
 
+extern ctf_file_t *ctf_simple_open (const char *, size_t, const char *, size_t,
+				   size_t, const char *, size_t, int *);
+extern ctf_file_t *ctf_bufopen (const ctf_sect_t *, const ctf_sect_t *,
+				const ctf_sect_t *, int *);
+extern ctf_file_t *ctf_create (int *);
+
 extern int ctf_errno (ctf_file_t *);
 extern const char *ctf_errmsg (int);
+extern ctf_id_t ctf_add_array (ctf_file_t *, uint32_t,
+			       const ctf_arinfo_t *);
+extern ctf_id_t ctf_add_const (ctf_file_t *, uint32_t, ctf_id_t);
+extern ctf_id_t ctf_add_enum_encoded (ctf_file_t *, uint32_t, const char *,
+				      const ctf_encoding_t *);
+extern ctf_id_t ctf_add_enum (ctf_file_t *, uint32_t, const char *);
+extern ctf_id_t ctf_add_float (ctf_file_t *, uint32_t,
+			       const char *, const ctf_encoding_t *);
+extern ctf_id_t ctf_add_forward (ctf_file_t *, uint32_t, const char *,
+				 uint32_t);
+extern ctf_id_t ctf_add_function (ctf_file_t *, uint32_t,
+				  const ctf_funcinfo_t *, const ctf_id_t *);
+extern ctf_id_t ctf_add_integer (ctf_file_t *, uint32_t, const char *,
+				 const ctf_encoding_t *);
+extern ctf_id_t ctf_add_slice (ctf_file_t *, uint32_t, ctf_id_t, const ctf_encoding_t *);
+extern ctf_id_t ctf_add_pointer (ctf_file_t *, uint32_t, ctf_id_t);
+extern ctf_id_t ctf_add_type (ctf_file_t *, ctf_file_t *, ctf_id_t);
+extern ctf_id_t ctf_add_typedef (ctf_file_t *, uint32_t, const char *,
+				 ctf_id_t);
+extern ctf_id_t ctf_add_restrict (ctf_file_t *, uint32_t, ctf_id_t);
+extern ctf_id_t ctf_add_struct (ctf_file_t *, uint32_t, const char *);
+extern ctf_id_t ctf_add_union (ctf_file_t *, uint32_t, const char *);
+extern ctf_id_t ctf_add_struct_sized (ctf_file_t *, uint32_t, const char *,
+				      size_t);
+extern ctf_id_t ctf_add_union_sized (ctf_file_t *, uint32_t, const char *,
+				     size_t);
+extern ctf_id_t ctf_add_volatile (ctf_file_t *, uint32_t, ctf_id_t);
+
+extern int ctf_add_enumerator (ctf_file_t *, ctf_id_t, const char *, int);
+extern int ctf_add_member (ctf_file_t *, ctf_id_t, const char *, ctf_id_t);
+extern int ctf_add_member_offset (ctf_file_t *, ctf_id_t, const char *,
+				  ctf_id_t, unsigned long);
+extern int ctf_add_member_encoded (ctf_file_t *, ctf_id_t, const char *,
+				   ctf_id_t, unsigned long,
+				   const ctf_encoding_t);
+
+extern int ctf_add_variable (ctf_file_t *, const char *, ctf_id_t);
+
+extern int ctf_set_array (ctf_file_t *, ctf_id_t, const ctf_arinfo_t *);
+
+extern int ctf_update (ctf_file_t *);
+extern ctf_snapshot_id_t ctf_snapshot (ctf_file_t *);
+extern int ctf_rollback (ctf_file_t *, ctf_snapshot_id_t);
+extern int ctf_discard (ctf_file_t *);
+extern int ctf_write (ctf_file_t *, int);
+extern int ctf_gzwrite (ctf_file_t * fp, gzFile fd);
+extern int ctf_compress_write (ctf_file_t * fp, int fd);
 
 extern void ctf_setdebug (int debug);
 extern int ctf_getdebug (void);
diff --git a/libctf/ctf-create.c b/libctf/ctf-create.c
new file mode 100644
index 0000000000..42012d8342
--- /dev/null
+++ b/libctf/ctf-create.c
@@ -0,0 +1,1547 @@
+/* CTF file creation.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+
+   This file is part of libctf.
+
+   libctf is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+   See the GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <ctf-impl.h>
+#include <sys/param.h>
+#include <assert.h>
+#include <string.h>
+#include <zlib.h>
+
+/* To create an empty CTF container, we just declare a zeroed header and call
+   ctf_bufopen() on it.  If ctf_bufopen succeeds, we mark the new container r/w
+   and initialize the dynamic members.  We set dtvstrlen to 1 to reserve the
+   first byte of the string table for a \0 byte, and we start assigning type
+   IDs at 1 because type ID 0 is used as a sentinel and a not-found
+   indicator.  */
+
+ctf_file_t *
+ctf_create (int *errp)
+{
+  static const ctf_header_t hdr = { .cth_preamble = { CTF_MAGIC, CTF_VERSION, 0 } };
+
+  ctf_dynhash_t *dthash;
+  ctf_dynhash_t *dvhash;
+  ctf_dynhash_t *dtbyname;
+  ctf_sect_t cts;
+  ctf_file_t *fp;
+
+  libctf_init_debug();
+  dthash = ctf_dynhash_create (ctf_hash_integer, ctf_hash_eq_integer,
+			       NULL, NULL);
+  if (dthash == NULL)
+    {
+      ctf_set_open_errno (errp, EAGAIN);
+      goto err;
+    }
+
+  dvhash = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
+			       NULL, NULL);
+  if (dvhash == NULL)
+    {
+      ctf_set_open_errno (errp, EAGAIN);
+      goto err_dt;
+    }
+
+  dtbyname = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
+				 free, NULL);
+  if (dtbyname == NULL)
+    {
+      ctf_set_open_errno (errp, EAGAIN);
+      goto err_dv;
+    }
+
+  cts.cts_name = _CTF_SECTION;
+  cts.cts_type = SHT_PROGBITS;
+  cts.cts_flags = 0;
+  cts.cts_data = &hdr;
+  cts.cts_size = sizeof (hdr);
+  cts.cts_entsize = 1;
+  cts.cts_offset = 0;
+
+  if ((fp = ctf_bufopen (&cts, NULL, NULL, errp)) == NULL)
+      goto err_dtbyname;
+
+  fp->ctf_flags |= LCTF_RDWR;
+  fp->ctf_dtbyname = dtbyname;
+  fp->ctf_dthash = dthash;
+  fp->ctf_dvhash = dvhash;
+  fp->ctf_dtvstrlen = 1;
+  fp->ctf_dtnextid = 1;
+  fp->ctf_dtoldid = 0;
+  fp->ctf_snapshots = 0;
+  fp->ctf_snapshot_lu = 0;
+
+  return fp;
+
+ err_dtbyname:
+  ctf_dynhash_destroy (dtbyname);
+ err_dv:
+  ctf_dynhash_destroy (dvhash);
+ err_dt:
+  ctf_dynhash_destroy (dthash);
+ err:
+  return NULL;
+}
+
+static unsigned char *
+ctf_copy_smembers (ctf_dtdef_t *dtd, uint32_t soff, unsigned char *t)
+{
+  ctf_dmdef_t *dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
+  ctf_member_t ctm;
+
+  for (; dmd != NULL; dmd = ctf_list_next (dmd))
+    {
+      if (dmd->dmd_name)
+	{
+	  ctm.ctm_name = soff;
+	  soff += strlen (dmd->dmd_name) + 1;
+	}
+      else
+	ctm.ctm_name = 0;
+
+      ctm.ctm_type = (uint32_t) dmd->dmd_type;
+      ctm.ctm_offset = (uint32_t) dmd->dmd_offset;
+
+      memcpy (t, &ctm, sizeof (ctm));
+      t += sizeof (ctm);
+    }
+
+  return t;
+}
+
+static unsigned char *
+ctf_copy_lmembers (ctf_dtdef_t *dtd, uint32_t soff, unsigned char *t)
+{
+  ctf_dmdef_t *dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
+  ctf_lmember_t ctlm;
+
+  for (; dmd != NULL; dmd = ctf_list_next (dmd))
+    {
+      if (dmd->dmd_name)
+	{
+	  ctlm.ctlm_name = soff;
+	  soff += strlen (dmd->dmd_name) + 1;
+	}
+      else
+	ctlm.ctlm_name = 0;
+
+      ctlm.ctlm_type = (uint32_t) dmd->dmd_type;
+      ctlm.ctlm_offsethi = CTF_OFFSET_TO_LMEMHI (dmd->dmd_offset);
+      ctlm.ctlm_offsetlo = CTF_OFFSET_TO_LMEMLO (dmd->dmd_offset);
+
+      memcpy (t, &ctlm, sizeof (ctlm));
+      t += sizeof (ctlm);
+    }
+
+  return t;
+}
+
+static unsigned char *
+ctf_copy_emembers (ctf_dtdef_t *dtd, uint32_t soff, unsigned char *t)
+{
+  ctf_dmdef_t *dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
+  ctf_enum_t cte;
+
+  for (; dmd != NULL; dmd = ctf_list_next (dmd))
+    {
+      cte.cte_name = soff;
+      cte.cte_value = dmd->dmd_value;
+      soff += strlen (dmd->dmd_name) + 1;
+      memcpy (t, &cte, sizeof (cte));
+      t += sizeof (cte);
+    }
+
+  return t;
+}
+
+static unsigned char *
+ctf_copy_membnames (ctf_dtdef_t *dtd, unsigned char *s)
+{
+  ctf_dmdef_t *dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
+  size_t len;
+
+  for (; dmd != NULL; dmd = ctf_list_next (dmd))
+    {
+      if (dmd->dmd_name == NULL)
+	continue;			/* Skip anonymous members.  */
+      len = strlen (dmd->dmd_name) + 1;
+      memcpy (s, dmd->dmd_name, len);
+      s += len;
+    }
+
+  return s;
+}
+
+/* Sort a newly-constructed static variable array.  */
+
+static int
+ctf_sort_var (const void *one_, const void *two_, void *strtab_)
+{
+  const ctf_varent_t *one = one_;
+  const ctf_varent_t *two = two_;
+  const char *strtab = strtab_;
+  const char *n1 = strtab + CTF_NAME_OFFSET (one->ctv_name);
+  const char *n2 = strtab + CTF_NAME_OFFSET (two->ctv_name);
+
+  return (strcmp (n1, n2));
+}
+
+/* If the specified CTF container is writable and has been modified, reload this
+   container with the updated type definitions.  In order to make this code and
+   the rest of libctf as simple as possible, we perform updates by taking the
+   dynamic type definitions and creating an in-memory CTF file containing the
+   definitions, and then call ctf_simple_open() on it.  This not only leverages
+   ctf_simple_open(), but also avoids having to bifurcate the rest of the library
+   code with different lookup paths for static and dynamic type definitions.  We
+   are therefore optimizing greatly for lookup over update, which we assume will
+   be an uncommon operation.  We perform one extra trick here for the benefit of
+   callers and to keep our code simple: ctf_simple_open() will return a new
+   ctf_file_t, but we want to keep the fp constant for the caller, so after
+   ctf_simple_open() returns, we use memcpy to swap the interior of the old and
+   new ctf_file_t's, and then free the old.  */
+int
+ctf_update (ctf_file_t *fp)
+{
+  ctf_file_t ofp, *nfp;
+  ctf_header_t hdr;
+  ctf_dtdef_t *dtd;
+  ctf_dvdef_t *dvd;
+  ctf_varent_t *dvarents;
+
+  unsigned char *s, *s0, *t;
+  unsigned long i;
+  size_t buf_size, type_size, nvars;
+  void *buf;
+  int err;
+
+  if (!(fp->ctf_flags & LCTF_RDWR))
+    return (ctf_set_errno (fp, ECTF_RDONLY));
+
+  /* Update required?  */
+  if (!(fp->ctf_flags & LCTF_DIRTY))
+    return 0;
+
+  /* Fill in an initial CTF header.  We will leave the label, object,
+     and function sections empty and only output a header, type section,
+     and string table.  The type section begins at a 4-byte aligned
+     boundary past the CTF header itself (at relative offset zero).  */
+
+  memset (&hdr, 0, sizeof (hdr));
+  hdr.cth_magic = CTF_MAGIC;
+  hdr.cth_version = CTF_VERSION;
+
+  if (fp->ctf_flags & LCTF_CHILD)
+    hdr.cth_parname = 1;		/* parname added just below.  */
+
+  /* Iterate through the dynamic type definition list and compute the
+     size of the CTF type section we will need to generate.  */
+
+  for (type_size = 0, dtd = ctf_list_next (&fp->ctf_dtdefs);
+       dtd != NULL; dtd = ctf_list_next (dtd))
+    {
+      uint32_t kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
+      uint32_t vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info);
+
+      if (dtd->dtd_data.ctt_size != CTF_LSIZE_SENT)
+	type_size += sizeof (ctf_stype_t);
+      else
+	type_size += sizeof (ctf_type_t);
+
+      switch (kind)
+	{
+	case CTF_K_INTEGER:
+	case CTF_K_FLOAT:
+	  type_size += sizeof (uint32_t);
+	  break;
+	case CTF_K_ARRAY:
+	  type_size += sizeof (ctf_array_t);
+	  break;
+	case CTF_K_SLICE:
+	  type_size += sizeof (ctf_slice_t);
+	  break;
+	case CTF_K_FUNCTION:
+	  type_size += sizeof (uint32_t) * (vlen + (vlen & 1));
+	  break;
+	case CTF_K_STRUCT:
+	case CTF_K_UNION:
+	  if (dtd->dtd_data.ctt_size < CTF_LSTRUCT_THRESH)
+	    type_size += sizeof (ctf_member_t) * vlen;
+	  else
+	    type_size += sizeof (ctf_lmember_t) * vlen;
+	  break;
+	case CTF_K_ENUM:
+	  type_size += sizeof (ctf_enum_t) * vlen;
+	  break;
+	}
+    }
+
+  /* Computing the number of entries in the CTF variable section is much
+     simpler.  */
+
+  for (nvars = 0, dvd = ctf_list_next (&fp->ctf_dvdefs);
+       dvd != NULL; dvd = ctf_list_next (dvd), nvars++);
+
+  /* Fill in the string table and type offset and size, compute the size
+     of the entire CTF buffer we need, and then allocate a new buffer and
+     memcpy the finished header to the start of the buffer.  */
+
+  hdr.cth_typeoff = hdr.cth_varoff + (nvars * sizeof (ctf_varent_t));
+  hdr.cth_stroff = hdr.cth_typeoff + type_size;
+  hdr.cth_strlen = fp->ctf_dtvstrlen;
+  if (fp->ctf_parname != NULL)
+    hdr.cth_strlen += strlen (fp->ctf_parname) + 1;
+
+  buf_size = sizeof (ctf_header_t) + hdr.cth_stroff + hdr.cth_strlen;
+
+  if ((buf = ctf_data_alloc (buf_size)) == NULL)
+    return (ctf_set_errno (fp, EAGAIN));
+
+  memcpy (buf, &hdr, sizeof (ctf_header_t));
+  t = (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_varoff;
+  s = s0 = (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_stroff;
+
+  s[0] = '\0';
+  s++;
+
+  if (fp->ctf_parname != NULL)
+    {
+      memcpy (s, fp->ctf_parname, strlen (fp->ctf_parname) + 1);
+      s += strlen (fp->ctf_parname) + 1;
+    }
+
+  /* Work over the variable list, translating everything into
+     ctf_varent_t's and filling out the string table, then sort the buffer
+     of ctf_varent_t's.  */
+
+  dvarents = (ctf_varent_t *) t;
+  for (i = 0, dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL;
+       dvd = ctf_list_next (dvd), i++)
+    {
+      ctf_varent_t *var = &dvarents[i];
+      size_t len = strlen (dvd->dvd_name) + 1;
+
+      var->ctv_name = (uint32_t) (s - s0);
+      var->ctv_type = dvd->dvd_type;
+      memcpy (s, dvd->dvd_name, len);
+      s += len;
+    }
+  assert (i == nvars);
+
+  qsort_r (dvarents, nvars, sizeof (ctf_varent_t), ctf_sort_var, s0);
+  t += sizeof (ctf_varent_t) * nvars;
+
+  assert (t == (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_typeoff);
+
+  /* We now take a final lap through the dynamic type definition list and
+     copy the appropriate type records and strings to the output buffer.  */
+
+  for (dtd = ctf_list_next (&fp->ctf_dtdefs);
+       dtd != NULL; dtd = ctf_list_next (dtd))
+    {
+
+      uint32_t kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
+      uint32_t vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info);
+
+      ctf_array_t cta;
+      uint32_t encoding;
+      size_t len;
+
+      if (dtd->dtd_name != NULL)
+	{
+	  dtd->dtd_data.ctt_name = (uint32_t) (s - s0);
+	  len = strlen (dtd->dtd_name) + 1;
+	  memcpy (s, dtd->dtd_name, len);
+	  s += len;
+	}
+      else
+	dtd->dtd_data.ctt_name = 0;
+
+      if (dtd->dtd_data.ctt_size != CTF_LSIZE_SENT)
+	len = sizeof (ctf_stype_t);
+      else
+	len = sizeof (ctf_type_t);
+
+      memcpy (t, &dtd->dtd_data, len);
+      t += len;
+
+      switch (kind)
+	{
+	case CTF_K_INTEGER:
+	case CTF_K_FLOAT:
+	  if (kind == CTF_K_INTEGER)
+	    {
+	      encoding = CTF_INT_DATA (dtd->dtd_u.dtu_enc.cte_format,
+				       dtd->dtd_u.dtu_enc.cte_offset,
+				       dtd->dtd_u.dtu_enc.cte_bits);
+	    }
+	  else
+	    {
+	      encoding = CTF_FP_DATA (dtd->dtd_u.dtu_enc.cte_format,
+				      dtd->dtd_u.dtu_enc.cte_offset,
+				      dtd->dtd_u.dtu_enc.cte_bits);
+	    }
+	  memcpy (t, &encoding, sizeof (encoding));
+	  t += sizeof (encoding);
+	  break;
+
+	case CTF_K_SLICE:
+	  memcpy (t, &dtd->dtd_u.dtu_slice, sizeof (struct ctf_slice));
+	  t += sizeof (struct ctf_slice);
+	  break;
+
+	case CTF_K_ARRAY:
+	  cta.cta_contents = (uint32_t) dtd->dtd_u.dtu_arr.ctr_contents;
+	  cta.cta_index = (uint32_t) dtd->dtd_u.dtu_arr.ctr_index;
+	  cta.cta_nelems = dtd->dtd_u.dtu_arr.ctr_nelems;
+	  memcpy (t, &cta, sizeof (cta));
+	  t += sizeof (cta);
+	  break;
+
+	case CTF_K_FUNCTION:
+	  {
+	    uint32_t *argv = (uint32_t *) (uintptr_t) t;
+	    uint32_t argc;
+
+	    for (argc = 0; argc < vlen; argc++)
+	      *argv++ = (uint32_t) dtd->dtd_u.dtu_argv[argc];
+
+	    if (vlen & 1)
+	      *argv++ = 0;	/* Pad to 4-byte boundary.  */
+
+	    t = (unsigned char *) argv;
+	    break;
+	  }
+
+	case CTF_K_STRUCT:
+	case CTF_K_UNION:
+	  if (dtd->dtd_data.ctt_size < CTF_LSTRUCT_THRESH)
+	    t = ctf_copy_smembers (dtd, (uint32_t) (s - s0), t);
+	  else
+	    t = ctf_copy_lmembers (dtd, (uint32_t) (s - s0), t);
+	  s = ctf_copy_membnames (dtd, s);
+	  break;
+
+	case CTF_K_ENUM:
+	  t = ctf_copy_emembers (dtd, (uint32_t) (s - s0), t);
+	  s = ctf_copy_membnames (dtd, s);
+	  break;
+	}
+    }
+  assert (t == (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_stroff);
+
+  /* Finally, we are ready to ctf_simple_open() the new container.  If this
+     is successful, we then switch nfp and fp and free the old container.  */
+
+  ctf_data_protect (buf, buf_size);
+
+  if ((nfp = ctf_simple_open (buf, buf_size, NULL, 0, 0, NULL, 0, &err)) == NULL)
+    {
+      ctf_data_free (buf, buf_size);
+      return (ctf_set_errno (fp, err));
+    }
+
+  (void) ctf_setmodel (nfp, ctf_getmodel (fp));
+  (void) ctf_import (nfp, fp->ctf_parent);
+
+  nfp->ctf_refcnt = fp->ctf_refcnt;
+  nfp->ctf_flags |= fp->ctf_flags & ~LCTF_DIRTY;
+  nfp->ctf_data.cts_data = NULL;	/* Force ctf_data_free() on close.  */
+  nfp->ctf_dthash = fp->ctf_dthash;
+  nfp->ctf_dtdefs = fp->ctf_dtdefs;
+  nfp->ctf_dtbyname = fp->ctf_dtbyname;
+  nfp->ctf_dvhash = fp->ctf_dvhash;
+  nfp->ctf_dvdefs = fp->ctf_dvdefs;
+  nfp->ctf_dtvstrlen = fp->ctf_dtvstrlen;
+  nfp->ctf_dtnextid = fp->ctf_dtnextid;
+  nfp->ctf_dtoldid = fp->ctf_dtnextid - 1;
+  nfp->ctf_snapshots = fp->ctf_snapshots + 1;
+  nfp->ctf_specific = fp->ctf_specific;
+
+  nfp->ctf_snapshot_lu = fp->ctf_snapshots;
+
+  fp->ctf_dtbyname = NULL;
+  fp->ctf_dthash = NULL;
+  memset (&fp->ctf_dtdefs, 0, sizeof (ctf_list_t));
+
+  fp->ctf_dvhash = NULL;
+  memset (&fp->ctf_dvdefs, 0, sizeof (ctf_list_t));
+
+  memcpy (&ofp, fp, sizeof (ctf_file_t));
+  memcpy (fp, nfp, sizeof (ctf_file_t));
+  memcpy (nfp, &ofp, sizeof (ctf_file_t));
+
+  /* Initialize the ctf_lookup_by_name top-level dictionary.  We keep an
+     array of type name prefixes and the corresponding ctf_dynhash to use.
+     NOTE: This code must be kept in sync with the code in ctf_bufopen().  */
+
+  fp->ctf_lookups[0].ctl_hash = fp->ctf_structs;
+  fp->ctf_lookups[1].ctl_hash = fp->ctf_unions;
+  fp->ctf_lookups[2].ctl_hash = fp->ctf_enums;
+  fp->ctf_lookups[3].ctl_hash = fp->ctf_names;
+
+  nfp->ctf_refcnt = 1;		/* Force nfp to be freed.  */
+  ctf_close (nfp);
+
+  return 0;
+}
+
+static char *
+ctf_prefixed_name (int kind, const char *name)
+{
+  char *prefixed;
+
+  switch (kind)
+    {
+    case CTF_K_STRUCT:
+      prefixed = ctf_strdup ("struct ");
+      break;
+    case CTF_K_UNION:
+      prefixed = ctf_strdup ("union ");
+      break;
+    case CTF_K_ENUM:
+      prefixed = ctf_strdup ("enum ");
+      break;
+    default:
+      prefixed = ctf_strdup ("");
+    }
+
+  prefixed = ctf_str_append (prefixed, name);
+  return prefixed;
+}
+
+void
+ctf_dtd_insert (ctf_file_t *fp, ctf_dtdef_t *dtd)
+{
+  ctf_dynhash_insert (fp->ctf_dthash, (void *) dtd->dtd_type, dtd);
+  ctf_list_append (&fp->ctf_dtdefs, dtd);
+  if (dtd->dtd_name)
+    {
+      int kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
+      ctf_dynhash_insert (fp->ctf_dtbyname, ctf_prefixed_name (kind,
+							       dtd->dtd_name),
+			  dtd);
+    }
+}
+
+void
+ctf_dtd_delete (ctf_file_t *fp, ctf_dtdef_t *dtd)
+{
+  ctf_dmdef_t *dmd, *nmd;
+  int kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
+
+  ctf_dynhash_remove (fp->ctf_dthash, (void *) dtd->dtd_type);
+
+  switch (kind)
+    {
+    case CTF_K_STRUCT:
+    case CTF_K_UNION:
+    case CTF_K_ENUM:
+      for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
+	   dmd != NULL; dmd = nmd)
+	{
+	  if (dmd->dmd_name != NULL)
+	    {
+	      ctf_free (dmd->dmd_name);
+	      fp->ctf_dtvstrlen -= strlen (dmd->dmd_name) + 1;
+	    }
+	  nmd = ctf_list_next (dmd);
+	  ctf_free (dmd);
+	}
+      break;
+    case CTF_K_FUNCTION:
+      ctf_free (dtd->dtd_u.dtu_argv);
+      break;
+    }
+
+  if (dtd->dtd_name)
+    {
+      char *name;
+
+      name = ctf_prefixed_name (kind, dtd->dtd_name);
+      ctf_dynhash_remove (fp->ctf_dtbyname, name);
+      free (name);
+
+      ctf_free (dtd->dtd_name);
+      fp->ctf_dtvstrlen -= strlen (dtd->dtd_name) + 1;
+    }
+
+  ctf_list_delete (&fp->ctf_dtdefs, dtd);
+  ctf_free (dtd);
+}
+
+ctf_dtdef_t *
+ctf_dtd_lookup (const ctf_file_t *fp, ctf_id_t type)
+{
+  return (ctf_dtdef_t *) ctf_dynhash_lookup (fp->ctf_dthash, (void *) type);
+}
+
+static ctf_id_t
+ctf_dtd_lookup_type_by_name (ctf_file_t *fp, int kind, const char *name)
+{
+  ctf_dtdef_t *dtd;
+  char *decorated = ctf_prefixed_name (kind, name);
+
+  dtd = (ctf_dtdef_t *) ctf_dynhash_lookup (fp->ctf_dtbyname, decorated);
+  free (decorated);
+
+  if (dtd)
+    return dtd->dtd_type;
+
+  return 0;
+}
+
+ctf_dtdef_t *
+ctf_dynamic_type (const ctf_file_t *fp, ctf_id_t id)
+{
+  ctf_id_t idx;
+
+  if ((fp->ctf_flags & LCTF_CHILD) && LCTF_TYPE_ISPARENT (fp, id))
+    fp = fp->ctf_parent;
+
+  idx = LCTF_TYPE_TO_INDEX(fp, id);
+
+  if (((unsigned long) idx > fp->ctf_typemax) &&
+      ((unsigned long) idx < fp->ctf_dtnextid))
+    return ctf_dtd_lookup (fp, id);
+  return NULL;
+}
+
+void
+ctf_dvd_insert (ctf_file_t *fp, ctf_dvdef_t *dvd)
+{
+  ctf_dynhash_insert (fp->ctf_dvhash, dvd->dvd_name, dvd);
+  ctf_list_append (&fp->ctf_dvdefs, dvd);
+}
+
+void
+ctf_dvd_delete (ctf_file_t *fp, ctf_dvdef_t *dvd)
+{
+  ctf_dynhash_remove (fp->ctf_dvhash, dvd->dvd_name);
+
+  ctf_free (dvd->dvd_name);
+  fp->ctf_dtvstrlen -= strlen (dvd->dvd_name) + 1;
+
+  ctf_list_delete (&fp->ctf_dvdefs, dvd);
+  ctf_free (dvd);
+}
+
+ctf_dvdef_t *
+ctf_dvd_lookup (const ctf_file_t *fp, const char *name)
+{
+  return (ctf_dvdef_t *) ctf_dynhash_lookup (fp->ctf_dvhash, name);
+}
+
+/* Discard all of the dynamic type definitions and variable definitions that
+   have been added to the container since the last call to ctf_update().  We
+   locate such types by scanning the dtd list and deleting elements that have
+   type IDs greater than ctf_dtoldid, which is set by ctf_update(), above, and
+   by scanning the variable list and deleting elements that have update IDs
+   equal to the current value of the last-update snapshot count (indicating that
+   they were added after the most recent call to ctf_update()).  */
+int
+ctf_discard (ctf_file_t *fp)
+{
+  ctf_snapshot_id_t last_update =
+    { fp->ctf_dtoldid,
+      fp->ctf_snapshot_lu + 1 };
+
+  /* Update required?  */
+  if (!(fp->ctf_flags & LCTF_DIRTY))
+    return 0;
+
+  return (ctf_rollback (fp, last_update));
+}
+
+ctf_snapshot_id_t
+ctf_snapshot (ctf_file_t *fp)
+{
+  ctf_snapshot_id_t snapid;
+  snapid.dtd_id = fp->ctf_dtnextid - 1;
+  snapid.snapshot_id = fp->ctf_snapshots++;
+  return snapid;
+}
+
+/* Like ctf_discard(), only discards everything after a particular ID.  */
+int
+ctf_rollback (ctf_file_t *fp, ctf_snapshot_id_t id)
+{
+  ctf_dtdef_t *dtd, *ntd;
+  ctf_dvdef_t *dvd, *nvd;
+
+  if (!(fp->ctf_flags & LCTF_RDWR))
+    return (ctf_set_errno (fp, ECTF_RDONLY));
+
+  if (fp->ctf_dtoldid > id.dtd_id)
+    return (ctf_set_errno (fp, ECTF_OVERROLLBACK));
+
+  if (fp->ctf_snapshot_lu >= id.snapshot_id)
+    return (ctf_set_errno (fp, ECTF_OVERROLLBACK));
+
+  for (dtd = ctf_list_next (&fp->ctf_dtdefs); dtd != NULL; dtd = ntd)
+    {
+      ntd = ctf_list_next (dtd);
+
+      if (LCTF_TYPE_TO_INDEX (fp, dtd->dtd_type) <= id.dtd_id)
+	continue;
+
+      ctf_dtd_delete (fp, dtd);
+    }
+
+  for (dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL; dvd = nvd)
+    {
+      nvd = ctf_list_next (dvd);
+
+      if (dvd->dvd_snapshots <= id.snapshot_id)
+	continue;
+
+      ctf_dvd_delete (fp, dvd);
+    }
+
+  fp->ctf_dtnextid = id.dtd_id + 1;
+  fp->ctf_snapshots = id.snapshot_id;
+
+  if (fp->ctf_snapshots == fp->ctf_snapshot_lu)
+    fp->ctf_flags &= ~LCTF_DIRTY;
+
+  return 0;
+}
+
+static ctf_id_t
+ctf_add_generic (ctf_file_t *fp, uint32_t flag, const char *name,
+		 ctf_dtdef_t **rp)
+{
+  ctf_dtdef_t *dtd;
+  ctf_id_t type;
+  char *s = NULL;
+
+  if (flag != CTF_ADD_NONROOT && flag != CTF_ADD_ROOT)
+    return (ctf_set_errno (fp, EINVAL));
+
+  if (!(fp->ctf_flags & LCTF_RDWR))
+    return (ctf_set_errno (fp, ECTF_RDONLY));
+
+  if (LCTF_INDEX_TO_TYPE (fp, fp->ctf_dtnextid, 1) > CTF_MAX_TYPE)
+    return (ctf_set_errno (fp, ECTF_FULL));
+
+  if (LCTF_INDEX_TO_TYPE (fp, fp->ctf_dtnextid, 1) == CTF_MAX_PTYPE)
+    return (ctf_set_errno (fp, ECTF_FULL));
+
+  if ((dtd = ctf_alloc (sizeof (ctf_dtdef_t))) == NULL)
+    return (ctf_set_errno (fp, EAGAIN));
+
+  if (name != NULL && (s = ctf_strdup (name)) == NULL)
+    {
+      ctf_free (dtd);
+      return (ctf_set_errno (fp, EAGAIN));
+    }
+
+  type = fp->ctf_dtnextid++;
+  type = LCTF_INDEX_TO_TYPE (fp, type, (fp->ctf_flags & LCTF_CHILD));
+
+  memset (dtd, 0, sizeof (ctf_dtdef_t));
+  dtd->dtd_name = s;
+  dtd->dtd_type = type;
+
+  if (s != NULL)
+    fp->ctf_dtvstrlen += strlen (s) + 1;
+
+  ctf_dtd_insert (fp, dtd);
+  fp->ctf_flags |= LCTF_DIRTY;
+
+  *rp = dtd;
+  return type;
+}
+
+/* When encoding integer sizes, we want to convert a byte count in the range
+   1-8 to the closest power of 2 (e.g. 3->4, 5->8, etc).  The clp2() function
+   is a clever implementation from "Hacker's Delight" by Henry Warren, Jr.  */
+static size_t
+clp2 (size_t x)
+{
+  x--;
+
+  x |= (x >> 1);
+  x |= (x >> 2);
+  x |= (x >> 4);
+  x |= (x >> 8);
+  x |= (x >> 16);
+
+  return (x + 1);
+}
+
+static ctf_id_t
+ctf_add_encoded (ctf_file_t *fp, uint32_t flag,
+		 const char *name, const ctf_encoding_t *ep, uint32_t kind)
+{
+  ctf_dtdef_t *dtd;
+  ctf_id_t type;
+
+  if (ep == NULL)
+    return (ctf_set_errno (fp, EINVAL));
+
+  if ((type = ctf_add_generic (fp, flag, name, &dtd)) == CTF_ERR)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  dtd->dtd_data.ctt_info = CTF_TYPE_INFO (kind, flag, 0);
+  dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, NBBY) / NBBY);
+  dtd->dtd_u.dtu_enc = *ep;
+
+  return type;
+}
+
+static ctf_id_t
+ctf_add_reftype (ctf_file_t *fp, uint32_t flag, ctf_id_t ref, uint32_t kind)
+{
+  ctf_dtdef_t *dtd;
+  ctf_id_t type;
+  ctf_file_t *tmp = fp;
+
+  if (ref == CTF_ERR || ref < 0 || ref > CTF_MAX_TYPE)
+    return (ctf_set_errno (fp, EINVAL));
+
+  if (ctf_lookup_by_id (&tmp, ref) == NULL)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  if ((type = ctf_add_generic (fp, flag, NULL, &dtd)) == CTF_ERR)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  dtd->dtd_data.ctt_info = CTF_TYPE_INFO (kind, flag, 0);
+  dtd->dtd_data.ctt_type = (uint32_t) ref;
+
+  return type;
+}
+
+ctf_id_t
+ctf_add_slice (ctf_file_t *fp, uint32_t flag, ctf_id_t ref,
+	       const ctf_encoding_t *ep)
+{
+  ctf_dtdef_t *dtd;
+  ctf_id_t type;
+  int kind;
+  const ctf_type_t *tp;
+  ctf_file_t *tmp = fp;
+
+  if (ep == NULL)
+    return (ctf_set_errno (fp, EINVAL));
+
+  if ((ep->cte_bits > 255) || (ep->cte_offset > 255))
+    return (ctf_set_errno (fp, ECTF_SLICEOVERFLOW));
+
+  if (ref == CTF_ERR || ref < 0 || ref > CTF_MAX_TYPE)
+    return (ctf_set_errno (fp, EINVAL));
+
+  if ((tp = ctf_lookup_by_id (&tmp, ref)) == NULL)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  kind = ctf_type_kind_unsliced (tmp, ref);
+  if ((kind != CTF_K_INTEGER) && (kind != CTF_K_FLOAT) &&
+      (kind != CTF_K_ENUM))
+    return (ctf_set_errno (fp, ECTF_NOTINTFP));
+
+  if ((type = ctf_add_generic (fp, flag, NULL, &dtd)) == CTF_ERR)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_SLICE, flag, 0);
+  dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, NBBY) / NBBY);
+  dtd->dtd_u.dtu_slice.cts_type = ref;
+  dtd->dtd_u.dtu_slice.cts_bits = ep->cte_bits;
+  dtd->dtd_u.dtu_slice.cts_offset = ep->cte_offset;
+
+  return type;
+}
+
+ctf_id_t
+ctf_add_integer (ctf_file_t *fp, uint32_t flag,
+		 const char *name, const ctf_encoding_t *ep)
+{
+  return (ctf_add_encoded (fp, flag, name, ep, CTF_K_INTEGER));
+}
+
+ctf_id_t
+ctf_add_float (ctf_file_t *fp, uint32_t flag,
+	       const char *name, const ctf_encoding_t *ep)
+{
+  return (ctf_add_encoded (fp, flag, name, ep, CTF_K_FLOAT));
+}
+
+ctf_id_t
+ctf_add_pointer (ctf_file_t *fp, uint32_t flag, ctf_id_t ref)
+{
+  return (ctf_add_reftype (fp, flag, ref, CTF_K_POINTER));
+}
+
+ctf_id_t
+ctf_add_array (ctf_file_t *fp, uint32_t flag, const ctf_arinfo_t *arp)
+{
+  ctf_dtdef_t *dtd;
+  ctf_id_t type;
+  ctf_file_t *tmp = fp;
+
+  if (arp == NULL)
+    return (ctf_set_errno (fp, EINVAL));
+
+  if (ctf_lookup_by_id (&tmp, arp->ctr_contents) == NULL)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  tmp = fp;
+  if (ctf_lookup_by_id (&tmp, arp->ctr_index) == NULL)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  if ((type = ctf_add_generic (fp, flag, NULL, &dtd)) == CTF_ERR)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_ARRAY, flag, 0);
+  dtd->dtd_data.ctt_size = 0;
+  dtd->dtd_u.dtu_arr = *arp;
+
+  return type;
+}
+
+int
+ctf_set_array (ctf_file_t *fp, ctf_id_t type, const ctf_arinfo_t *arp)
+{
+  ctf_dtdef_t *dtd = ctf_dtd_lookup (fp, type);
+
+  if (!(fp->ctf_flags & LCTF_RDWR))
+    return (ctf_set_errno (fp, ECTF_RDONLY));
+
+  if (dtd == NULL
+      || LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info) != CTF_K_ARRAY)
+    return (ctf_set_errno (fp, ECTF_BADID));
+
+  fp->ctf_flags |= LCTF_DIRTY;
+  dtd->dtd_u.dtu_arr = *arp;
+
+  return 0;
+}
+
+ctf_id_t
+ctf_add_function (ctf_file_t *fp, uint32_t flag,
+		  const ctf_funcinfo_t *ctc, const ctf_id_t *argv)
+{
+  ctf_dtdef_t *dtd;
+  ctf_id_t type;
+  uint32_t vlen;
+  ctf_id_t *vdat = NULL;
+  ctf_file_t *tmp = fp;
+  size_t i;
+
+  if (ctc == NULL || (ctc->ctc_flags & ~CTF_FUNC_VARARG) != 0
+      || (ctc->ctc_argc != 0 && argv == NULL))
+    return (ctf_set_errno (fp, EINVAL));
+
+  vlen = ctc->ctc_argc;
+  if (ctc->ctc_flags & CTF_FUNC_VARARG)
+    vlen++;	       /* Add trailing zero to indicate varargs (see below).  */
+
+  if (ctf_lookup_by_id (&tmp, ctc->ctc_return) == NULL)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  for (i = 0; i < ctc->ctc_argc; i++)
+    {
+      tmp = fp;
+      if (ctf_lookup_by_id (&tmp, argv[i]) == NULL)
+	return CTF_ERR;		/* errno is set for us.  */
+    }
+
+  if (vlen > CTF_MAX_VLEN)
+    return (ctf_set_errno (fp, EOVERFLOW));
+
+  if (vlen != 0 && (vdat = ctf_alloc (sizeof (ctf_id_t) * vlen)) == NULL)
+    return (ctf_set_errno (fp, EAGAIN));
+
+  if ((type = ctf_add_generic (fp, flag, NULL, &dtd)) == CTF_ERR)
+    {
+      ctf_free (vdat);
+      return CTF_ERR;		   /* errno is set for us.  */
+    }
+
+  dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_FUNCTION, flag, vlen);
+  dtd->dtd_data.ctt_type = (uint32_t) ctc->ctc_return;
+
+  memcpy (vdat, argv, sizeof (ctf_id_t) * ctc->ctc_argc);
+  if (ctc->ctc_flags & CTF_FUNC_VARARG)
+    vdat[vlen - 1] = 0;		   /* Add trailing zero to indicate varargs.  */
+  dtd->dtd_u.dtu_argv = vdat;
+
+  return type;
+}
+
+ctf_id_t
+ctf_add_struct_sized (ctf_file_t *fp, uint32_t flag, const char *name,
+		      size_t size)
+{
+  ctf_hash_t *hp = fp->ctf_structs;
+  ctf_dtdef_t *dtd;
+  ctf_id_t type = 0;
+
+  /* Promote forwards to structs.  */
+
+  if (name != NULL)
+    {
+      type = ctf_hash_lookup_type (hp, fp, name);
+      if (type == 0)
+	type = ctf_dtd_lookup_type_by_name (fp, CTF_K_STRUCT, name);
+    }
+
+  if (type != 0 && ctf_type_kind (fp, type) == CTF_K_FORWARD)
+    dtd = ctf_dtd_lookup (fp, type);
+  else if ((type = ctf_add_generic (fp, flag, name, &dtd)) == CTF_ERR)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_STRUCT, flag, 0);
+
+  if (size > CTF_MAX_SIZE)
+    {
+      dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
+      dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (size);
+      dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO (size);
+    }
+  else
+    dtd->dtd_data.ctt_size = (uint32_t) size;
+
+  return type;
+}
+
+ctf_id_t
+ctf_add_struct (ctf_file_t *fp, uint32_t flag, const char *name)
+{
+  return (ctf_add_struct_sized (fp, flag, name, 0));
+}
+
+ctf_id_t
+ctf_add_union_sized (ctf_file_t *fp, uint32_t flag, const char *name,
+		     size_t size)
+{
+  ctf_hash_t *hp = fp->ctf_unions;
+  ctf_dtdef_t *dtd;
+  ctf_id_t type = 0;
+
+  /* Promote forwards to unions.  */
+  if (name != NULL)
+    {
+      type = ctf_hash_lookup_type (hp, fp, name);
+      if (type == 0)
+	type = ctf_dtd_lookup_type_by_name (fp, CTF_K_UNION, name);
+    }
+
+  if (type != 0 && ctf_type_kind (fp, type) == CTF_K_FORWARD)
+    dtd = ctf_dtd_lookup (fp, type);
+  else if ((type = ctf_add_generic (fp, flag, name, &dtd)) == CTF_ERR)
+    return CTF_ERR;		/* errno is set for us */
+
+  dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_UNION, flag, 0);
+
+  if (size > CTF_MAX_SIZE)
+    {
+      dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
+      dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (size);
+      dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO (size);
+    }
+  else
+    dtd->dtd_data.ctt_size = (uint32_t) size;
+
+  return type;
+}
+
+ctf_id_t
+ctf_add_union (ctf_file_t *fp, uint32_t flag, const char *name)
+{
+  return (ctf_add_union_sized (fp, flag, name, 0));
+}
+
+ctf_id_t
+ctf_add_enum (ctf_file_t *fp, uint32_t flag, const char *name)
+{
+  ctf_hash_t *hp = fp->ctf_enums;
+  ctf_dtdef_t *dtd;
+  ctf_id_t type = 0;
+
+  /* Promote forwards to enums.  */
+  if (name != NULL)
+    {
+      type = ctf_hash_lookup_type (hp, fp, name);
+      if (type == 0)
+	type = ctf_dtd_lookup_type_by_name (fp, CTF_K_ENUM, name);
+    }
+
+  if (type != 0 && ctf_type_kind (fp, type) == CTF_K_FORWARD)
+    dtd = ctf_dtd_lookup (fp, type);
+  else if ((type = ctf_add_generic (fp, flag, name, &dtd)) == CTF_ERR)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_ENUM, flag, 0);
+  dtd->dtd_data.ctt_size = fp->ctf_dmodel->ctd_int;
+
+  return type;
+}
+
+ctf_id_t
+ctf_add_enum_encoded (ctf_file_t *fp, uint32_t flag, const char *name,
+		      const ctf_encoding_t *ep)
+{
+  ctf_hash_t *hp = fp->ctf_enums;
+  ctf_id_t type = 0;
+
+  /* First, create the enum if need be, using most of the same machinery as
+     ctf_add_enum(), to ensure that we do not allow things past that are not
+     enums or forwards to them.  (This includes other slices: you cannot slice a
+     slice, which would be a useless thing to do anyway.)  */
+
+  if (name != NULL)
+    {
+      type = ctf_hash_lookup_type (hp, fp, name);
+      if (type == 0)
+	type = ctf_dtd_lookup_type_by_name (fp, CTF_K_ENUM, name);
+    }
+
+  if (type != 0)
+    {
+      if ((ctf_type_kind (fp, type) != CTF_K_FORWARD) &&
+	  (ctf_type_kind_unsliced (fp, type) != CTF_K_ENUM))
+	return (ctf_set_errno (fp, ECTF_NOTINTFP));
+    }
+  else if ((type = ctf_add_enum (fp, flag, name)) == CTF_ERR)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  /* Now attach a suitable slice to it.  */
+
+  return ctf_add_slice (fp, flag, type, ep);
+}
+
+ctf_id_t
+ctf_add_forward (ctf_file_t *fp, uint32_t flag, const char *name,
+		 uint32_t kind)
+{
+  ctf_hash_t *hp;
+  ctf_dtdef_t *dtd;
+  ctf_id_t type = 0;
+
+  switch (kind)
+    {
+    case CTF_K_STRUCT:
+      hp = fp->ctf_structs;
+      break;
+    case CTF_K_UNION:
+      hp = fp->ctf_unions;
+      break;
+    case CTF_K_ENUM:
+      hp = fp->ctf_enums;
+      break;
+    default:
+      return (ctf_set_errno (fp, ECTF_NOTSUE));
+    }
+
+  /* If the type is already defined or exists as a forward tag, just
+     return the ctf_id_t of the existing definition.  */
+
+  if (name != NULL)
+    {
+      if (((type = ctf_hash_lookup_type (hp, fp, name)) != 0)
+	  || (type = ctf_dtd_lookup_type_by_name (fp, kind, name)) != 0)
+	return type;
+    }
+
+  if ((type = ctf_add_generic (fp, flag, name, &dtd)) == CTF_ERR)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_FORWARD, flag, 0);
+  dtd->dtd_data.ctt_type = kind;
+
+  return type;
+}
+
+ctf_id_t
+ctf_add_typedef (ctf_file_t *fp, uint32_t flag, const char *name,
+		 ctf_id_t ref)
+{
+  ctf_dtdef_t *dtd;
+  ctf_id_t type;
+  ctf_file_t *tmp = fp;
+
+  if (ref == CTF_ERR || ref < 0 || ref > CTF_MAX_TYPE)
+    return (ctf_set_errno (fp, EINVAL));
+
+  if (ctf_lookup_by_id (&tmp, ref) == NULL)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  if ((type = ctf_add_generic (fp, flag, name, &dtd)) == CTF_ERR)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_TYPEDEF, flag, 0);
+  dtd->dtd_data.ctt_type = (uint32_t) ref;
+
+  return type;
+}
+
+ctf_id_t
+ctf_add_volatile (ctf_file_t *fp, uint32_t flag, ctf_id_t ref)
+{
+  return (ctf_add_reftype (fp, flag, ref, CTF_K_VOLATILE));
+}
+
+ctf_id_t
+ctf_add_const (ctf_file_t *fp, uint32_t flag, ctf_id_t ref)
+{
+  return (ctf_add_reftype (fp, flag, ref, CTF_K_CONST));
+}
+
+ctf_id_t
+ctf_add_restrict (ctf_file_t *fp, uint32_t flag, ctf_id_t ref)
+{
+  return (ctf_add_reftype (fp, flag, ref, CTF_K_RESTRICT));
+}
+
+int
+ctf_add_enumerator (ctf_file_t *fp, ctf_id_t enid, const char *name,
+		    int value)
+{
+  ctf_dtdef_t *dtd = ctf_dtd_lookup (fp, enid);
+  ctf_dmdef_t *dmd;
+
+  uint32_t kind, vlen, root;
+  char *s;
+
+  if (name == NULL)
+    return (ctf_set_errno (fp, EINVAL));
+
+  if (!(fp->ctf_flags & LCTF_RDWR))
+    return (ctf_set_errno (fp, ECTF_RDONLY));
+
+  if (dtd == NULL)
+    return (ctf_set_errno (fp, ECTF_BADID));
+
+  kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
+  root = LCTF_INFO_ISROOT (fp, dtd->dtd_data.ctt_info);
+  vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info);
+
+  if (kind != CTF_K_ENUM)
+    return (ctf_set_errno (fp, ECTF_NOTENUM));
+
+  if (vlen == CTF_MAX_VLEN)
+    return (ctf_set_errno (fp, ECTF_DTFULL));
+
+  for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
+       dmd != NULL; dmd = ctf_list_next (dmd))
+    {
+      if (strcmp (dmd->dmd_name, name) == 0)
+	return (ctf_set_errno (fp, ECTF_DUPLICATE));
+    }
+
+  if ((dmd = ctf_alloc (sizeof (ctf_dmdef_t))) == NULL)
+    return (ctf_set_errno (fp, EAGAIN));
+
+  if ((s = ctf_strdup (name)) == NULL)
+    {
+      ctf_free (dmd);
+      return (ctf_set_errno (fp, EAGAIN));
+    }
+
+  dmd->dmd_name = s;
+  dmd->dmd_type = CTF_ERR;
+  dmd->dmd_offset = 0;
+  dmd->dmd_value = value;
+
+  dtd->dtd_data.ctt_info = CTF_TYPE_INFO (kind, root, vlen + 1);
+  ctf_list_append (&dtd->dtd_u.dtu_members, dmd);
+
+  fp->ctf_dtvstrlen += strlen (s) + 1;
+  fp->ctf_flags |= LCTF_DIRTY;
+
+  return 0;
+}
+
+int
+ctf_add_member_offset (ctf_file_t *fp, ctf_id_t souid, const char *name,
+		       ctf_id_t type, unsigned long bit_offset)
+{
+  ctf_dtdef_t *dtd = ctf_dtd_lookup (fp, souid);
+  ctf_dmdef_t *dmd;
+
+  ssize_t msize, malign, ssize;
+  uint32_t kind, vlen, root;
+  char *s = NULL;
+
+  if (!(fp->ctf_flags & LCTF_RDWR))
+    return (ctf_set_errno (fp, ECTF_RDONLY));
+
+  if (dtd == NULL)
+    return (ctf_set_errno (fp, ECTF_BADID));
+
+  kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
+  root = LCTF_INFO_ISROOT (fp, dtd->dtd_data.ctt_info);
+  vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info);
+
+  if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
+    return (ctf_set_errno (fp, ECTF_NOTSOU));
+
+  if (vlen == CTF_MAX_VLEN)
+    return (ctf_set_errno (fp, ECTF_DTFULL));
+
+  if (name != NULL)
+    {
+      for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
+	   dmd != NULL; dmd = ctf_list_next (dmd))
+	{
+	  if (dmd->dmd_name != NULL && strcmp (dmd->dmd_name, name) == 0)
+	    return (ctf_set_errno (fp, ECTF_DUPLICATE));
+	}
+    }
+
+  if ((msize = ctf_type_size (fp, type)) == CTF_ERR ||
+      (malign = ctf_type_align (fp, type)) == CTF_ERR)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  if ((dmd = ctf_alloc (sizeof (ctf_dmdef_t))) == NULL)
+    return (ctf_set_errno (fp, EAGAIN));
+
+  if (name != NULL && (s = ctf_strdup (name)) == NULL)
+    {
+      ctf_free (dmd);
+      return (ctf_set_errno (fp, EAGAIN));
+    }
+
+  dmd->dmd_name = s;
+  dmd->dmd_type = type;
+  dmd->dmd_value = -1;
+
+  if (kind == CTF_K_STRUCT && vlen != 0)
+    {
+      if (bit_offset == (unsigned long) - 1)
+	{
+	  /* Natural alignment.  */
+
+	  ctf_dmdef_t *lmd = ctf_list_prev (&dtd->dtd_u.dtu_members);
+	  ctf_id_t ltype = ctf_type_resolve (fp, lmd->dmd_type);
+	  size_t off = lmd->dmd_offset;
+
+	  ctf_encoding_t linfo;
+	  ssize_t lsize;
+
+	  if (ctf_type_encoding (fp, ltype, &linfo) != CTF_ERR)
+	    off += linfo.cte_bits;
+	  else if ((lsize = ctf_type_size (fp, ltype)) != CTF_ERR)
+	    off += lsize * NBBY;
+
+	  /* Round up the offset of the end of the last member to
+	     the next byte boundary, convert 'off' to bytes, and
+	     then round it up again to the next multiple of the
+	     alignment required by the new member.  Finally,
+	     convert back to bits and store the result in
+	     dmd_offset.  Technically we could do more efficient
+	     packing if the new member is a bit-field, but we're
+	     the "compiler" and ANSI says we can do as we choose.  */
+
+	  off = roundup (off, NBBY) / NBBY;
+	  off = roundup (off, MAX (malign, 1));
+	  dmd->dmd_offset = off * NBBY;
+	  ssize = off + msize;
+	}
+      else
+	{
+	  /* Specified offset in bits.  */
+
+	  dmd->dmd_offset = bit_offset;
+	  ssize = ctf_get_ctt_size (fp, &dtd->dtd_data, NULL, NULL);
+	  ssize = MAX (ssize, (bit_offset / NBBY) + msize);
+	}
+    }
+  else
+    {
+      dmd->dmd_offset = 0;
+      ssize = ctf_get_ctt_size (fp, &dtd->dtd_data, NULL, NULL);
+      ssize = MAX (ssize, msize);
+    }
+
+  if (ssize > CTF_MAX_SIZE)
+    {
+      dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
+      dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (ssize);
+      dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO (ssize);
+    }
+  else
+    dtd->dtd_data.ctt_size = (uint32_t) ssize;
+
+  dtd->dtd_data.ctt_info = CTF_TYPE_INFO (kind, root, vlen + 1);
+  ctf_list_append (&dtd->dtd_u.dtu_members, dmd);
+
+  if (s != NULL)
+    fp->ctf_dtvstrlen += strlen (s) + 1;
+
+  fp->ctf_flags |= LCTF_DIRTY;
+  return 0;
+}
+
+int
+ctf_add_member_encoded (ctf_file_t *fp, ctf_id_t souid, const char *name,
+			ctf_id_t type, unsigned long bit_offset,
+			const ctf_encoding_t encoding)
+{
+  ctf_dtdef_t *dtd = ctf_dtd_lookup (fp, type);
+  int kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
+  int otype = type;
+
+  if ((kind != CTF_K_INTEGER) && (kind != CTF_K_FLOAT) && (kind != CTF_K_ENUM))
+    return (ctf_set_errno (fp, ECTF_NOTINTFP));
+
+  if ((type = ctf_add_slice (fp, CTF_ADD_NONROOT, otype, &encoding)) == CTF_ERR)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  return ctf_add_member_offset (fp, souid, name, type, bit_offset);
+}
+
+int
+ctf_add_member (ctf_file_t *fp, ctf_id_t souid, const char *name,
+		ctf_id_t type)
+{
+  return ctf_add_member_offset (fp, souid, name, type, (unsigned long) - 1);
+}
+
+int
+ctf_add_variable (ctf_file_t *fp, const char *name, ctf_id_t ref)
+{
+  ctf_dvdef_t *dvd;
+  ctf_file_t *tmp = fp;
+
+  if (!(fp->ctf_flags & LCTF_RDWR))
+    return (ctf_set_errno (fp, ECTF_RDONLY));
+
+  if (ctf_dvd_lookup (fp, name) != NULL)
+    return (ctf_set_errno (fp, ECTF_DUPLICATE));
+
+  if (ctf_lookup_by_id (&tmp, ref) == NULL)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  if ((dvd = ctf_alloc (sizeof (ctf_dvdef_t))) == NULL)
+    return (ctf_set_errno (fp, EAGAIN));
+
+  if (name != NULL && (dvd->dvd_name = ctf_strdup (name)) == NULL)
+    {
+      ctf_free (dvd);
+      return (ctf_set_errno (fp, EAGAIN));
+    }
+  dvd->dvd_type = ref;
+  dvd->dvd_snapshots = fp->ctf_snapshots;
+
+  ctf_dvd_insert (fp, dvd);
+
+  fp->ctf_dtvstrlen += strlen (name) + 1;
+  fp->ctf_flags |= LCTF_DIRTY;
+  return 0;
+}
+
+/* Write the compressed CTF data stream to the specified gzFile descriptor.
+   This is useful for saving the results of dynamic CTF containers.  */
+int
+ctf_gzwrite (ctf_file_t *fp, gzFile fd)
+{
+  const unsigned char *buf = fp->ctf_base;
+  ssize_t resid = fp->ctf_size;
+  ssize_t len;
+
+  while (resid != 0)
+    {
+      if ((len = gzwrite (fd, buf, resid)) <= 0)
+	return (ctf_set_errno (fp, errno));
+      resid -= len;
+      buf += len;
+    }
+
+  return 0;
+}
+
+/* Compress the specified CTF data stream and write it to the specified file
+   descriptor.  */
+int
+ctf_compress_write (ctf_file_t *fp, int fd)
+{
+  unsigned char *buf;
+  unsigned char *bp;
+  ctf_header_t h;
+  ctf_header_t *hp = &h;
+  ssize_t header_len = sizeof (ctf_header_t);
+  ssize_t compress_len;
+  size_t max_compress_len = compressBound (fp->ctf_size - header_len);
+  ssize_t len;
+  int rc;
+  int err = 0;
+
+  memcpy (hp, fp->ctf_base, header_len);
+  hp->cth_flags |= CTF_F_COMPRESS;
+
+  if ((buf = ctf_data_alloc (max_compress_len)) == NULL)
+    return (ctf_set_errno (fp, ECTF_ZALLOC));
+
+  compress_len = max_compress_len;
+  if ((rc = compress (buf, (uLongf *) & compress_len,
+		      fp->ctf_base + header_len,
+		      fp->ctf_size - header_len)) != Z_OK)
+    {
+      ctf_dprintf ("zlib deflate err: %s\n", zError (rc));
+      err = ctf_set_errno (fp, ECTF_COMPRESS);
+      goto ret;
+    }
+
+  while (header_len > 0)
+    {
+      if ((len = write (fd, hp, header_len)) < 0)
+	{
+	  err = ctf_set_errno (fp, errno);
+	  goto ret;
+	}
+      header_len -= len;
+      hp += len;
+    }
+
+  bp = buf;
+  while (compress_len > 0)
+    {
+      if ((len = write (fd, bp, compress_len)) < 0)
+	{
+	  err = ctf_set_errno (fp, errno);
+	  goto ret;
+	}
+      compress_len -= len;
+      bp += len;
+    }
+
+ret:
+  ctf_data_free (buf, max_compress_len);
+  return err;
+}
+
+/* Write the uncompressed CTF data stream to the specified file descriptor.
+   This is useful for saving the results of dynamic CTF containers.  */
+int
+ctf_write (ctf_file_t *fp, int fd)
+{
+  const unsigned char *buf = fp->ctf_base;
+  ssize_t resid = fp->ctf_size;
+  ssize_t len;
+
+  while (resid != 0)
+    {
+      if ((len = write (fd, buf, resid)) < 0)
+	return (ctf_set_errno (fp, errno));
+      resid -= len;
+      buf += len;
+    }
+
+  return 0;
+}
diff --git a/libctf/ctf-lookup.c b/libctf/ctf-lookup.c
new file mode 100644
index 0000000000..e76afb6e0a
--- /dev/null
+++ b/libctf/ctf-lookup.c
@@ -0,0 +1,63 @@
+/* Type lookup.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+
+   This file is part of libctf.
+
+   libctf is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+   See the GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <ctf-impl.h>
+#include <elf.h>
+#include <string.h>
+
+/* Return the pointer to the internal CTF type data corresponding to the
+   given type ID.  If the ID is invalid, the function returns NULL.
+   This function is not exported outside of the library.  */
+
+const ctf_type_t *
+ctf_lookup_by_id (ctf_file_t **fpp, ctf_id_t type)
+{
+  ctf_file_t *fp = *fpp;	/* Caller passes in starting CTF container.  */
+  ctf_id_t idx;
+
+  if ((fp->ctf_flags & LCTF_CHILD) && LCTF_TYPE_ISPARENT (fp, type)
+      && (fp = fp->ctf_parent) == NULL)
+    {
+      (void) ctf_set_errno (*fpp, ECTF_NOPARENT);
+      return NULL;
+    }
+
+  idx = LCTF_TYPE_TO_INDEX (fp, type);
+  if (idx > 0 && (unsigned long) idx <= fp->ctf_typemax)
+    {
+      *fpp = fp;		/* Function returns ending CTF container.  */
+      return (LCTF_INDEX_TO_TYPEPTR (fp, idx));
+    }
+
+  /* If this container is writable, check for a dynamic type.  */
+
+  if (fp->ctf_flags & LCTF_RDWR)
+    {
+      ctf_dtdef_t *dtd;
+
+      if ((dtd = ctf_dynamic_type (fp, type)) != NULL)
+	{
+	  *fpp = fp;
+	  return &dtd->dtd_data;
+	}
+    }
+  (void) ctf_set_errno (*fpp, ECTF_BADID);
+  return NULL;
+}
+
-- 
2.21.0.237.gd0cfaa883d

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v2 17/19] libctf: debug dumping
  2019-05-17 22:10 [PATCH v2 00/19] libctf, and CTF support for objdump and readelf Nick Alcock
  2019-05-17 22:10 ` [PATCH v2 12/19] libctf: lookups by name and symbol Nick Alcock
  2019-05-17 22:10 ` [PATCH v2 05/19] libctf: error handling Nick Alcock
@ 2019-05-17 22:10 ` Nick Alcock
  2019-05-17 22:10 ` [PATCH v2 01/19] include: new header ctf.h: file format description Nick Alcock
                   ` (17 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nick Alcock @ 2019-05-17 22:10 UTC (permalink / raw)
  To: binutils

This introduces ctf_dump(), an iterator which returns a series of
strings, each representing a debugging dump of one item from a given
section in the CTF file.  The items may be multiline: a callback is
provided to allow the caller to decorate each line as they desire before
the line is returned.

Note to reviewers: I wrote this code only last month: it has never been
in a release, so it is correspondingly more likely to contain bugs.

Changes from v1:
 - Correct erroneous license (GPLv2+ -> v3+) and reset copyright years.
 - Adjust to ctf_free() prototype change

libctf/
	* ctf-dump.c: New.

include/
	* ctf-api.h (ctf_dump_decorate_f): New.
	(ctf_dump_state_t): new.
	(ctf_dump): New.
---
 include/ctf-api.h |   9 +
 libctf/ctf-dump.c | 595 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 604 insertions(+)
 create mode 100644 libctf/ctf-dump.c

diff --git a/include/ctf-api.h b/include/ctf-api.h
index 14a61520bb..929deee194 100644
--- a/include/ctf-api.h
+++ b/include/ctf-api.h
@@ -218,6 +218,11 @@ typedef int ctf_label_f (const char *name, const ctf_lblinfo_t *info,
 typedef int ctf_archive_member_f (ctf_file_t *fp, const char *name, void *arg);
 typedef int ctf_archive_raw_member_f (const char *name, const void *content,
 				      size_t len, void *arg);
+typedef char *ctf_dump_decorate_f (ctf_sect_names_t sect,
+				   char *line, void *arg);
+
+typedef struct ctf_dump_state ctf_dump_state_t;
+
 extern ctf_file_t *ctf_simple_open (const char *, size_t, const char *, size_t,
 				   size_t, const char *, size_t, int *);
 extern ctf_file_t *ctf_bfdopen (struct bfd *, int *);
@@ -296,6 +301,10 @@ extern int ctf_archive_iter (const ctf_archive_t *, ctf_archive_member_f *,
 			     void *);
 extern int ctf_archive_raw_iter (const ctf_archive_t *,
 				 ctf_archive_raw_member_f *, void *);
+extern char *ctf_dump (ctf_file_t *, ctf_dump_state_t **state,
+		       ctf_sect_names_t sect, ctf_dump_decorate_f *,
+		       void *arg);
+
 extern ctf_id_t ctf_add_array (ctf_file_t *, uint32_t,
 			       const ctf_arinfo_t *);
 extern ctf_id_t ctf_add_const (ctf_file_t *, uint32_t, ctf_id_t);
diff --git a/libctf/ctf-dump.c b/libctf/ctf-dump.c
new file mode 100644
index 0000000000..28f31e4872
--- /dev/null
+++ b/libctf/ctf-dump.c
@@ -0,0 +1,595 @@
+/* Textual dumping of CTF data.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+
+   This file is part of libctf.
+
+   libctf is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+   See the GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <ctf-impl.h>
+#include <string.h>
+
+/* One item to be dumped, in string form.  */
+
+typedef struct ctf_dump_item
+{
+  ctf_list_t cdi_list;
+  char *cdi_item;
+} ctf_dump_item_t;
+
+/* Cross-call state for dumping.  Basically just enough to track the section in
+   use and a list of return strings.  */
+
+struct ctf_dump_state
+{
+  ctf_sect_names_t cds_sect;
+  ctf_file_t *cds_fp;
+  ctf_dump_item_t *cds_current;
+  ctf_list_t cds_items;
+};
+
+/* Cross-call state for ctf_dump_member. */
+
+typedef struct ctf_dump_membstate
+{
+  char **cdm_str;
+  ctf_file_t *cdm_fp;
+} ctf_dump_membstate_t;
+
+static int
+ctf_dump_append (ctf_dump_state_t *state, char *str)
+{
+  ctf_dump_item_t *cdi;
+
+  if ((cdi = ctf_alloc (sizeof (struct ctf_dump_item))) == NULL)
+    return (ctf_set_errno (state->cds_fp, ENOMEM));
+
+  cdi->cdi_item = str;
+  ctf_list_append (&state->cds_items, cdi);
+  return 0;
+}
+
+static void
+ctf_dump_free (ctf_dump_state_t *state)
+{
+  ctf_dump_item_t *cdi, *next_cdi;
+
+  if (state == NULL)
+    return;
+
+  for (cdi = ctf_list_next (&state->cds_items); cdi != NULL;
+       cdi = next_cdi)
+    {
+      free (cdi->cdi_item);
+      next_cdi = ctf_list_next (cdi);
+      ctf_free (cdi);
+    }
+}
+
+/* Slices need special handling to distinguish them from their referenced
+   type.  */
+
+static int
+ctf_is_slice (ctf_file_t *fp, ctf_id_t id, ctf_encoding_t *enc)
+{
+  int kind = ctf_type_kind (fp, id);
+
+  return (((kind == CTF_K_INTEGER) || (kind == CTF_K_ENUM)
+	   || (kind == CTF_K_FLOAT))
+	  && ctf_type_reference (fp, id) != CTF_ERR
+	  && ctf_type_encoding (fp, id, enc) != CTF_ERR);
+}
+
+/* Return a dump for a single type, without member info: but do show the
+   type's references.  */
+
+static char *
+ctf_dump_format_type (ctf_file_t *fp, ctf_id_t id)
+{
+  ctf_id_t new_id;
+  char *str = NULL, *bit = NULL, *buf = NULL;
+
+  new_id = id;
+  do
+    {
+      ctf_encoding_t enc;
+
+      id = new_id;
+      buf = ctf_type_aname (fp, id);
+      if (!buf)
+	goto oom;
+
+      /* Slices get a different print representation.  */
+
+      if (ctf_is_slice (fp, id, &enc))
+	{
+	  ctf_type_encoding (fp, id, &enc);
+	  if (asprintf (&bit, " %lx: [slice 0x%x:0x%x]",
+			id, enc.cte_offset, enc.cte_bits) < 0)
+	    goto oom;
+	}
+      else
+	{
+	  if (asprintf (&bit, " %lx: %s (size %lx)", id, buf[0] == '\0' ?
+			"(nameless)" : buf, ctf_type_size (fp, id)) < 0)
+	    goto oom;
+	}
+      free (buf);
+      buf = NULL;
+      str = ctf_str_append (str, bit);
+      free (bit);
+      bit = NULL;
+
+      new_id = ctf_type_reference (fp, id);
+      if (new_id != CTF_ERR)
+	str = ctf_str_append (str, " ->");
+    } while (new_id != CTF_ERR);
+
+  if (ctf_errno (fp) != ECTF_NOTREF)
+    {
+      free (str);
+      return NULL;
+    }
+
+  return str;
+
+ oom:
+  free (buf);
+  free (str);
+  free (bit);
+  ctf_set_errno (fp, ENOMEM);
+  return NULL;
+}
+
+/* Dump a single label into the cds_items.  */
+
+static int
+ctf_dump_label (const char *name, const ctf_lblinfo_t *info,
+		void *arg)
+{
+  char *str;
+  char *typestr;
+  ctf_dump_state_t *state = arg;
+
+  if (asprintf (&str, "%s -> ", name) < 0)
+    return (ctf_set_errno (state->cds_fp, ENOMEM));
+
+  if ((typestr = ctf_dump_format_type (state->cds_fp, info->ctb_type)) == NULL)
+    {
+      free (str);
+      return CTF_ERR;			/* errno is set for us.  */
+    }
+
+  str = ctf_str_append (str, typestr);
+  free (typestr);
+
+  ctf_dump_append (state, str);
+  return 0;
+}
+
+/* Dump all the object entries into the cds_items.  (There is no iterator for
+   this section, so we just do it in a loop, and this function handles all of
+   them, rather than only one.  */
+
+static int
+ctf_dump_objts (ctf_file_t *fp, ctf_dump_state_t *state)
+{
+  size_t i;
+
+  for (i = 0; i < fp->ctf_nsyms; i++)
+    {
+      char *str;
+      char *typestr;
+      const char *sym_name;
+      ctf_id_t type;
+
+      if ((type = ctf_lookup_by_symbol (state->cds_fp, i)) < 0)
+	switch (ctf_errno (state->cds_fp))
+	  {
+	    /* Most errors are just an indication that this symbol is not a data
+	       symbol, but this one indicates that we were called wrong, on a
+	       CTF file with no associated symbol table.  */
+	  case ECTF_NOSYMTAB:
+	    return CTF_ERR;
+	  case ECTF_NOTDATA:
+	  case ECTF_NOTYPEDAT:
+	    continue;
+	  }
+
+      /* Variable name.  */
+      sym_name = ctf_lookup_symbol_name (fp, i);
+      if (sym_name[0] == '\0')
+	{
+	  if (asprintf (&str, "%lx -> ", i) < 0)
+	    return (ctf_set_errno (fp, ENOMEM));
+	}
+      else
+	{
+	  if (asprintf (&str, "%s (%lx) -> ", sym_name, i) < 0)
+	    return (ctf_set_errno (fp, ENOMEM));
+	}
+
+      /* Variable type.  */
+      if ((typestr = ctf_dump_format_type (state->cds_fp, type)) == NULL)
+	{
+	  free (str);
+	  return CTF_ERR;		/* errno is set for us.  */
+	}
+
+      str = ctf_str_append (str, typestr);
+      free (typestr);
+
+      ctf_dump_append (state, str);
+    }
+  return 0;
+}
+
+/* Dump all the function entries into the cds_items.  (As above, there is no
+   iterator for this section.)  */
+
+static int
+ctf_dump_funcs (ctf_file_t *fp, ctf_dump_state_t *state)
+{
+  size_t i;
+
+  for (i = 0; i < fp->ctf_nsyms; i++)
+    {
+      char *str ;
+      char *bit;
+      const char *sym_name;
+      ctf_funcinfo_t fi;
+      ctf_id_t type;
+      size_t j;
+      ctf_id_t *args;
+
+      if ((type = ctf_func_info (state->cds_fp, i, &fi)) < 0)
+	switch (ctf_errno (state->cds_fp))
+	  {
+	    /* Most errors are just an indication that this symbol is not a data
+	       symbol, but this one indicates that we were called wrong, on a
+	       CTF file with no associated symbol table.  */
+	  case ECTF_NOSYMTAB:
+	    return CTF_ERR;
+	  case ECTF_NOTDATA:
+	  case ECTF_NOTYPEDAT:
+	    continue;
+	  }
+      if ((args = calloc (fi.ctc_argc, sizeof (ctf_id_t))) == NULL)
+	return (ctf_set_errno (fp, ENOMEM));
+
+      /* Return type.  */
+      if ((str = ctf_type_aname (state->cds_fp, type)) == NULL)
+	goto err;
+
+      str = ctf_str_append (str, " ");
+      free (bit);
+
+      /* Function name.  */
+
+      sym_name = ctf_lookup_symbol_name (fp, i);
+      if (sym_name[0] == '\0')
+	{
+	  if (asprintf (&bit, "%lx ", i) < 0)
+	    goto oom;
+	}
+      else
+	{
+	  if (asprintf (&bit, "%s (%lx) ", sym_name, i) < 0)
+	    goto oom;
+	}
+      str = ctf_str_append (str, bit);
+      str = ctf_str_append (str, " (");
+
+      /* Function arguments.  */
+
+      if (ctf_func_args (state->cds_fp, i, fi.ctc_argc, args) < 0)
+	goto err;
+
+      for (j = 0; j < fi.ctc_argc; j++)
+	{
+	  if ((bit = ctf_type_aname (state->cds_fp, args[j])) == NULL)
+	    goto err;
+	  str = ctf_str_append (str, bit);
+	  if ((j < fi.ctc_argc - 1) || (fi.ctc_flags & CTF_FUNC_VARARG))
+	    str = ctf_str_append (str, ", ");
+	  free (bit);
+	}
+
+      if (fi.ctc_flags & CTF_FUNC_VARARG)
+	str = ctf_str_append (str, "...");
+      str = ctf_str_append (str, ")");
+
+      free (args);
+      ctf_dump_append (state, str);
+      continue;
+
+    oom:
+      free (args);
+      free (str);
+      return (ctf_set_errno (fp, ENOMEM));
+    err:
+      free (args);
+      free (str);
+      return CTF_ERR;		/* errno is set for us.  */
+    }
+  return 0;
+}
+
+/* Dump a single variable into the cds_items.  */
+static int
+ctf_dump_var (const char *name, ctf_id_t type, void *arg)
+{
+  char *str;
+  char *typestr;
+  ctf_dump_state_t *state = arg;
+
+  if (asprintf (&str, "%s -> ", name) < 0)
+    return (ctf_set_errno (state->cds_fp, ENOMEM));
+
+  if ((typestr = ctf_dump_format_type (state->cds_fp, type)) == NULL)
+    {
+      free (str);
+      return CTF_ERR;			/* errno is set for us.  */
+    }
+
+  str = ctf_str_append (str, typestr);
+  free (typestr);
+
+  ctf_dump_append (state, str);
+  return 0;
+}
+
+/* Dump a single member into the string in the membstate.  */
+static int
+ctf_dump_member (const char *name, ctf_id_t id, unsigned long offset,
+		  int depth, void *arg)
+{
+  ctf_dump_membstate_t *state = arg;
+  char *typestr = NULL;
+  char *bit = NULL;
+  ctf_encoding_t ep;
+  ssize_t i;
+
+  for (i = 0; i < depth; i++)
+    *state->cdm_str = ctf_str_append (*state->cdm_str, "    ");
+
+  if ((typestr = ctf_type_aname (state->cdm_fp, id)) == NULL)
+    goto oom;
+
+  if (asprintf (&bit, "    [0x%lx] (ID 0x%lx) (kind %i) %s %s (aligned at 0x%lx",
+		offset, id, ctf_type_kind (state->cdm_fp, id), typestr, name,
+		ctf_type_align (state->cdm_fp, id)) < 0)
+    goto oom;
+  *state->cdm_str = ctf_str_append (*state->cdm_str, bit);
+  free (typestr);
+  free (bit);
+  typestr = NULL;
+  bit = NULL;
+
+  if ((ctf_type_kind (state->cdm_fp, id) == CTF_K_INTEGER)
+      || (ctf_type_kind (state->cdm_fp, id) == CTF_K_FLOAT)
+      || (ctf_is_slice (state->cdm_fp, id, &ep) == CTF_K_ENUM))
+    {
+      ctf_type_encoding (state->cdm_fp, id, &ep);
+      if (asprintf (&bit, ", format 0x%x, offset:bits 0x%x:0x%x", ep.cte_format,
+		    ep.cte_offset, ep.cte_bits) < 0)
+	goto oom;
+      *state->cdm_str = ctf_str_append (*state->cdm_str, bit);
+      free (bit);
+      bit = NULL;
+    }
+
+  *state->cdm_str = ctf_str_append (*state->cdm_str, ")\n");
+  return 0;
+
+ oom:
+  free (typestr);
+  free (bit);
+  return (ctf_set_errno (state->cdm_fp, ENOMEM));
+}
+
+/* Dump a single type into the cds_items.  */
+
+static int
+ctf_dump_type (ctf_id_t id, void *arg)
+{
+  char *str;
+  ctf_dump_state_t *state = arg;
+  ctf_dump_membstate_t membstate = { &str, state->cds_fp };
+  size_t len;
+
+  if ((str = ctf_dump_format_type (state->cds_fp, id)) == NULL)
+    goto err;
+
+  str = ctf_str_append (str, "\n");
+  if ((ctf_type_visit (state->cds_fp, id, ctf_dump_member, &membstate)) < 0)
+    goto err;
+
+  /* Trim off the last linefeed added by ctf_dump_member().  */
+  len = strlen (str);
+  if (str[len-1] == '\n')
+    str[len-1] = '\0';
+
+  ctf_dump_append (state, str);
+  return 0;
+
+ err:
+  free (str);
+  return CTF_ERR;			/* errno is set for us.  */
+}
+
+/* Dump the string table into the cds_items.  */
+
+static int
+ctf_dump_str (ctf_file_t *fp, ctf_dump_state_t *state)
+{
+  const char *s = fp->ctf_str[CTF_STRTAB_0].cts_strs;
+
+  for (; s < fp->ctf_str[CTF_STRTAB_0].cts_strs +
+	 fp->ctf_str[CTF_STRTAB_0].cts_len;)
+    {
+      char *str;
+      if (asprintf (&str, "%lx: %s", s - fp->ctf_str[CTF_STRTAB_0].cts_strs,
+		    s) < 0)
+	return (ctf_set_errno (fp, ENOMEM));
+      ctf_dump_append (state, str);
+      s += strlen (s) + 1;
+    }
+
+  return 0;
+}
+
+/* Dump a particular section of a CTF file, in textual form.  Call with a
+   pointer to a NULL STATE: each call emits a dynamically allocated string
+   containing a description of one entity in the specified section, in order.
+   Only the first call (with a NULL state) may vary SECT.  Once the CTF section
+   has been entirely dumped, the call returns NULL and frees and annuls the
+   STATE, ready for another section to be dumped.  The returned textual content
+   may span multiple lines: between each call the FUNC is called with one
+   textual line at a time, and should return a suitably decorated line (it can
+   allocate a new one and return it if it likes).  */
+
+char *
+ctf_dump (ctf_file_t *fp, ctf_dump_state_t **statep, ctf_sect_names_t sect,
+	  ctf_dump_decorate_f *func, void *arg)
+{
+  char *str;
+  char *line;
+  ctf_dump_state_t *state = NULL;
+
+  if (*statep == NULL)
+    {
+      /* Data collection.  Transforming a call-at-a-time iterator into a
+	 return-at-a-time iterator in a language without call/cc is annoying. It
+	 is easiest to simply collect everything at once and then return it bit
+	 by bit.  The first call will take (much) longer than otherwise, but the
+	 amortized time needed is the same.  */
+
+      if ((*statep = ctf_alloc (sizeof (struct ctf_dump_state))) == NULL)
+	{
+	  ctf_set_errno (fp, ENOMEM);
+	  goto end;
+	}
+      state = *statep;
+
+      memset (state, 0, sizeof (struct ctf_dump_state));
+      state->cds_fp = fp;
+      state->cds_sect = sect;
+
+      switch (sect)
+	{
+	case CTF_SECT_HEADER:
+	  /* Nothing doable (yet): entire header is discarded after read-phase.  */
+	  str = strdup ("");
+	  break;
+	case CTF_SECT_LABEL:
+	  if (ctf_label_iter (fp, ctf_dump_label, state) < 0)
+	    {
+	      if (ctf_errno (fp) != ECTF_NOLABELDATA)
+		goto end;		/* errno is set for us.  */
+	      ctf_set_errno (fp, 0);
+	    }
+	  break;
+	case CTF_SECT_OBJT:
+	  if (ctf_dump_objts (fp, state) < 0)
+	    goto end;			/* errno is set for us.  */
+	  break;
+	case CTF_SECT_FUNC:
+	  if (ctf_dump_funcs (fp, state) < 0)
+	    goto end;			/* errno is set for us.  */
+	  break;
+	case CTF_SECT_VAR:
+	  if (ctf_variable_iter (fp, ctf_dump_var, state) < 0)
+	    goto end;			/* errno is set for us.  */
+	  break;
+	case CTF_SECT_TYPE:
+	  if (ctf_type_iter (fp, ctf_dump_type, state) < 0)
+	    goto end;			/* errno is set for us.  */
+	  break;
+	case CTF_SECT_STR:
+	  ctf_dump_str (fp, state);
+	  break;
+	default:
+	  ctf_set_errno (fp, ECTF_DUMPSECTUNKNOWN);
+	  goto end;
+	}
+    }
+  else
+    {
+      state = *statep;
+
+      if (state->cds_sect != sect)
+	{
+	  ctf_set_errno (fp, ECTF_DUMPSECTCHANGED);
+	  goto end;
+	}
+    }
+
+  if (state->cds_current == NULL)
+    state->cds_current = ctf_list_next (&state->cds_items);
+  else
+    state->cds_current = ctf_list_next (state->cds_current);
+
+  if (state->cds_current == NULL)
+    goto end;
+
+  /* Hookery.  There is some extra complexity to preserve linefeeds within each
+     item while removing linefeeds at the end.  */
+  if (func)
+    {
+      size_t len;
+
+      str = NULL;
+      for (line = state->cds_current->cdi_item; line && *line; )
+	{
+	  char *nline = line;
+	  char *ret;
+
+	  nline = strchr (line, '\n');
+	  if (nline)
+	    nline[0] = '\0';
+
+	  ret = func (sect, line, arg);
+	  str = ctf_str_append (str, ret);
+	  str = ctf_str_append (str, "\n");
+	  if (ret != line)
+	    free (ret);
+
+	  if (nline)
+	    {
+	      nline[0] = '\n';
+	      nline++;
+	    }
+
+	  line = nline;
+	}
+
+      len = strlen (str);
+
+      if (str[len-1] == '\n')
+	str[len-1] = '\0';
+    }
+  else
+    str = strdup (state->cds_current->cdi_item);
+
+  ctf_set_errno (fp, 0);
+  return str;
+
+ end:
+  ctf_dump_free (state);
+  ctf_free (state);
+  ctf_set_errno (fp, 0);
+  *statep = NULL;
+  return NULL;
+}
-- 
2.21.0.237.gd0cfaa883d

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v2 00/19] libctf, and CTF support for objdump and readelf
@ 2019-05-17 22:10 Nick Alcock
  2019-05-17 22:10 ` [PATCH v2 12/19] libctf: lookups by name and symbol Nick Alcock
                   ` (20 more replies)
  0 siblings, 21 replies; 31+ messages in thread
From: Nick Alcock @ 2019-05-17 22:10 UTC (permalink / raw)
  To: binutils

This is the second posting of libctf, containing fixes for every review comment
received in the last cycle, and introduction of backward-compatibility code for
the old v1 format found in some enterprise Linux kernel packages, and nothing
else: in particular, the various format changes and prototype changes planned
have not landed yet.  (The backward-compatibility code is preparation for this,
since it is that code which will be enhanced and disentangled when the format
changes land.)

(The format description is the same as it was in the last patch series: see that
series for more info. It *will* change shortly -- though in a fashion that will
not leave it unrecognizably different -- and when it changes I'll probably write
something in texinfo or something to describe in a more GNUish fashion.)

Joseph: you'll probably be interested in patches 3, 9, 10, and 15 in particular,
for their BFDization and portability fixes.

Nick Alcock (19):
  include: new header ctf.h: file format description
  include: new header ctf-api.h
  libctf: lowest-level memory allocation and debug-dumping wrappers
  libctf: low-level list manipulation and helper utilities
  libctf: error handling
  libctf: hashing
  libctf: implementation definitions related to file creation
  libctf: creation functions
  libctf: opening
  libctf: ELF file opening via BFD
  libctf: core type lookup
  libctf: lookups by name and symbol
  libctf: type copying
  libctf: library version enforcement
  libctf: mmappable archives
  libctf: labels
  libctf: debug dumping
  libctf: build system
  binutils: CTF support for objdump and readelf

 Makefile.def                    |    6 +
 Makefile.in                     |  991 +++-
 binutils/Makefile.am            |   10 +-
 binutils/Makefile.in            |   18 +-
 binutils/aclocal.m4             |   10 +-
 binutils/doc/Makefile.in        |    9 +-
 binutils/doc/binutils.texi      |   12 +
 binutils/doc/ctf.options.texi   |   19 +
 binutils/objdump.c              |  156 +-
 binutils/readelf.c              |  206 +
 configure                       |    2 +-
 configure.ac                    |    2 +-
 include/ctf-api.h               |  363 ++
 include/ctf.h                   |  561 +++
 libctf/Makefile.am              |   31 +
 libctf/Makefile.in              |  767 ++++
 {binutils => libctf}/aclocal.m4 |   99 +-
 libctf/config.h.in              |  113 +
 libctf/configure                | 7462 +++++++++++++++++++++++++++++++
 libctf/configure.ac             |   63 +
 libctf/ctf-archive.c            |  617 +++
 libctf/ctf-create.c             | 2032 +++++++++
 libctf/ctf-decl.c               |  195 +
 libctf/ctf-dump.c               |  595 +++
 libctf/ctf-error.c              |   93 +
 libctf/ctf-hash.c               |  277 ++
 libctf/ctf-impl.h               |  374 ++
 libctf/ctf-labels.c             |  138 +
 libctf/ctf-lookup.c             |  427 ++
 libctf/ctf-open-bfd.c           |  264 ++
 libctf/ctf-open.c               | 1687 +++++++
 libctf/ctf-subr.c               |  259 ++
 libctf/ctf-types.c              | 1023 +++++
 libctf/ctf-util.c               |  176 +
 libctf/elf.h                    |   61 +
 libctf/swap.h                   |   60 +
 36 files changed, 19107 insertions(+), 71 deletions(-)
 create mode 100644 binutils/doc/ctf.options.texi
 create mode 100644 include/ctf-api.h
 create mode 100644 include/ctf.h
 create mode 100644 libctf/Makefile.am
 create mode 100644 libctf/Makefile.in
 copy {binutils => libctf}/aclocal.m4 (95%)
 create mode 100644 libctf/config.h.in
 create mode 100755 libctf/configure
 create mode 100644 libctf/configure.ac
 create mode 100644 libctf/ctf-archive.c
 create mode 100644 libctf/ctf-create.c
 create mode 100644 libctf/ctf-decl.c
 create mode 100644 libctf/ctf-dump.c
 create mode 100644 libctf/ctf-error.c
 create mode 100644 libctf/ctf-hash.c
 create mode 100644 libctf/ctf-impl.h
 create mode 100644 libctf/ctf-labels.c
 create mode 100644 libctf/ctf-lookup.c
 create mode 100644 libctf/ctf-open-bfd.c
 create mode 100644 libctf/ctf-open.c
 create mode 100644 libctf/ctf-subr.c
 create mode 100644 libctf/ctf-types.c
 create mode 100644 libctf/ctf-util.c
 create mode 100644 libctf/elf.h
 create mode 100644 libctf/swap.h

-- 
2.21.0.237.gd0cfaa883d

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v2 01/19] include: new header ctf.h: file format description
  2019-05-17 22:10 [PATCH v2 00/19] libctf, and CTF support for objdump and readelf Nick Alcock
                   ` (2 preceding siblings ...)
  2019-05-17 22:10 ` [PATCH v2 17/19] libctf: debug dumping Nick Alcock
@ 2019-05-17 22:10 ` Nick Alcock
  2019-05-17 22:10 ` [PATCH v2 07/19] libctf: implementation definitions related to file creation Nick Alcock
                   ` (16 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nick Alcock @ 2019-05-17 22:10 UTC (permalink / raw)
  To: binutils

The data structures and macros in this header can be used, if desired,
to access or create CTF files directly, without going through libctf,
though this should rarely be necessary in practice.

libctf relies on this header as its description of the CTF file format.

Changes from v1:
 - Correct erroneous license (GPLv2+ -> v3+) and reset copyright years.
 - Include compatibility definitions for old file format versions
   (will migrate into a new ctf-compat.h, included from ctf.h, in the
   near future).  v1 is more compact than v2, but has severe
   limitations on numbers of types and the like: v3 is planned to
   include the compactness of v1 and the scalability of v2.

include/
	* ctf.h: New file.
---
 include/ctf.h | 517 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 517 insertions(+)
 create mode 100644 include/ctf.h

diff --git a/include/ctf.h b/include/ctf.h
new file mode 100644
index 0000000000..6580a2143c
--- /dev/null
+++ b/include/ctf.h
@@ -0,0 +1,517 @@
+/* CTF format description.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+
+   This file is part of libctf.
+
+   libctf is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+   See the GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef	_CTF_H
+#define	_CTF_H
+
+#include <sys/types.h>
+#include <limits.h>
+#include <stdint.h>
+
+
+#ifdef	__cplusplus
+extern "C"
+{
+#endif
+
+/* CTF - Compact ANSI-C Type Format
+
+   This file format can be used to compactly represent the information needed
+   by a debugger to interpret the ANSI-C types used by a given program.
+   Traditionally, this kind of information is generated by the compiler when
+   invoked with the -g flag and is stored in "stabs" strings or in the more
+   modern DWARF format.  CTF provides a representation of only the information
+   that is relevant to debugging a complex, optimized C program such as the
+   operating system kernel in a form that is significantly more compact than
+   the equivalent stabs or DWARF representation.  The format is data-model
+   independent, so consumers do not need different code depending on whether
+   they are 32-bit or 64-bit programs; libctf automatically compensates for
+   endianness variations.  CTF assumes that a standard ELF symbol table is
+   available for use in the debugger, and uses the structure and data of the
+   symbol table to avoid storing redundant information.  The CTF data may be
+   compressed on disk or in memory, indicated by a bit in the header.  CTF may
+   be interpreted in a raw disk file, or it may be stored in an ELF section,
+   typically named .ctf.  Data structures are aligned so that a raw CTF file or
+   CTF ELF section may be manipulated using mmap(2).
+
+   The CTF file or section itself has the following structure:
+
+   +--------+--------+---------+----------+----------+-------+--------+
+   |  file  |  type  |  data   | function | variable | data  | string |
+   | header | labels | objects |   info   |   info   | types | table  |
+   +--------+--------+---------+----------+----------+-------+--------+
+
+   The file header stores a magic number and version information, encoding
+   flags, and the byte offset of each of the sections relative to the end of the
+   header itself.  If the CTF data has been uniquified against another set of
+   CTF data, a reference to that data also appears in the the header.  This
+   reference is the name of the label corresponding to the types uniquified
+   against.
+
+   Following the header is a list of labels, used to group the types included in
+   the data types section.  Each label is accompanied by a type ID i.  A given
+   label refers to the group of types whose IDs are in the range [0, i].
+
+   Data object and function records are stored in the same order as they appear
+   in the corresponding symbol table, except that symbols marked SHN_UNDEF are
+   not stored and symbols that have no type data are padded out with zeroes.
+   For each data object, the type ID (a small integer) is recorded.  For each
+   function, the type ID of the return type and argument types is recorded.
+
+   Variable records (as distinct from data objects) provide a modicum of support
+   for non-ELF systems, mapping a variable name to a CTF type ID.  The variable
+   names are sorted into ASCIIbetical order, permitting binary searching.
+
+   The data types section is a list of variable size records that represent each
+   type, in order by their ID.  The types themselves form a directed graph,
+   where each node may contain one or more outgoing edges to other type nodes,
+   denoted by their ID.
+
+   Strings are recorded as a string table ID (0 or 1) and a byte offset into the
+   string table.  String table 0 is the internal CTF string table.  String table
+   1 is the external string table, which is the string table associated with the
+   ELF symbol table for this object.  CTF does not record any strings that are
+   already in the symbol table, and the CTF string table does not contain any
+   duplicated strings.
+
+   If the CTF data has been merged with another parent CTF object, some outgoing
+   edges may refer to type nodes that exist in another CTF object.  The debugger
+   and libctf library are responsible for connecting the appropriate objects
+   together so that the full set of types can be explored and manipulated.
+
+   This connection is done purely using the ctf_import() function.  There is no
+   notation anywhere in the child CTF file indicating which parent it is
+   connected to: it is the debugger's responsibility to track this.  */
+
+#define CTF_MAX_TYPE	0xfffffffe	/* Max type identifier value.  */
+#define CTF_MAX_PTYPE	0x7fffffff	/* Max parent type identifier value.  */
+#define CTF_MAX_NAME 0x7fffffff		/* Max offset into a string table.  */
+#define CTF_MAX_VLEN	0xffffff /* Max struct, union, enum members or args.  */
+
+/* See ctf_type_t */
+#define CTF_MAX_SIZE	0xfffffffe	/* Max size of a v2 type in bytes. */
+#define CTF_LSIZE_SENT	0xffffffff	/* Sentinel for v2 ctt_size.  */
+
+# define CTF_MAX_TYPE_V1	0xffff	/* Max type identifier value.  */
+# define CTF_MAX_PTYPE_V1	0x7fff	/* Max parent type identifier value.  */
+# define CTF_MAX_VLEN_V1	0x3ff	/* Max struct, union, enums or args.  */
+# define CTF_MAX_SIZE_V1	0xfffe	/* Max size of a type in bytes. */
+# define CTF_LSIZE_SENT_V1	0xffff	/* Sentinel for v1 ctt_size.  */
+
+  /* Start of actual data structure definitions.
+
+     Every field in these structures must have corresponding code in the
+     endianness-swapping machinery in libctf/ctf-open.c.  */
+
+typedef struct ctf_preamble
+{
+  unsigned short ctp_magic;	/* Magic number (CTF_MAGIC).  */
+  unsigned char ctp_version;	/* Data format version number (CTF_VERSION).  */
+  unsigned char ctp_flags;	/* Flags (see below).  */
+} ctf_preamble_t;
+
+typedef struct ctf_header
+{
+  ctf_preamble_t cth_preamble;
+  uint32_t cth_parlabel;	/* Ref to name of parent lbl uniq'd against.  */
+  uint32_t cth_parname;		/* Ref to basename of parent.  */
+  uint32_t cth_lbloff;		/* Offset of label section.  */
+  uint32_t cth_objtoff;		/* Offset of object section.  */
+  uint32_t cth_funcoff;		/* Offset of function section.  */
+  uint32_t cth_varoff;		/* Offset of variable section.  */
+  uint32_t cth_typeoff;		/* Offset of type section.  */
+  uint32_t cth_stroff;		/* Offset of string section.  */
+  uint32_t cth_strlen;		/* Length of string section in bytes.  */
+} ctf_header_t;
+
+#define cth_magic   cth_preamble.ctp_magic
+#define cth_version cth_preamble.ctp_version
+#define cth_flags   cth_preamble.ctp_flags
+
+#define CTF_MAGIC	0xdff2	/* Magic number identifying header.  */
+
+/* Data format version number.  */
+
+/* v1 upgraded to v2 is not quite the same as native v2 (the boundary between
+   parent and child types is different), and you can write it out again via
+   ctf_compress_write(), so we must track whether the thing was originally v1 or
+   not.  If we were writing the header from scratch, we would add a *pair* of
+   version number fields to allow for this, but this will do for now.  (A flag
+   will not do, because we need to encode both the version we came from and the
+   version we went to, not just "we were upgraded".) */
+
+# define CTF_VERSION_1 1
+# define CTF_VERSION_1_UPGRADED_3 2
+# define CTF_VERSION_2 3
+
+#define CTF_VERSION_3 4
+#define CTF_VERSION CTF_VERSION_3 /* Current version.  */
+
+#define CTF_F_COMPRESS	0x1	/* Data buffer is compressed by libctf.  */
+
+typedef struct ctf_lblent
+{
+  uint32_t ctl_label;		/* Ref to name of label.  */
+  uint32_t ctl_type;		/* Last type associated with this label.  */
+} ctf_lblent_t;
+
+typedef struct ctf_varent
+{
+  uint32_t ctv_name;		/* Reference to name in string table.  */
+  uint32_t ctv_type;		/* Index of type of this variable.  */
+} ctf_varent_t;
+
+/* In format v2, type sizes, measured in bytes, come in two flavours.  Nearly
+   all of them fit into a (UINT_MAX - 1), and thus can be stored in the ctt_size
+   member of a ctf_stype_t.  The maximum value for these sizes is CTF_MAX_SIZE.
+   Types larger than this must be stored in the ctf_lsize member of a
+   ctf_type_t.  Use of this member is indicated by the presence of
+   CTF_LSIZE_SENT in ctt_size.  */
+
+/* In v1, the same applies, only the limit is (USHRT_MAX - 1) and
+   CTF_MAX_SIZE_V1, and CTF_LSIZE_SENT_V1 is the sentinel.  */
+
+typedef struct ctf_stype_v1
+{
+  uint32_t ctt_name;		/* Reference to name in string table.  */
+  unsigned short ctt_info;	/* Encoded kind, variant length (see below).  */
+#ifndef __GNUC__
+  union
+  {
+    unsigned short _size;	/* Size of entire type in bytes.  */
+    unsigned short _type;	/* Reference to another type.  */
+  } _u;
+#else
+  __extension__
+  union
+  {
+    unsigned short ctt_size;	/* Size of entire type in bytes.  */
+    unsigned short ctt_type;	/* Reference to another type.  */
+  };
+#endif
+} ctf_stype_v1_t;
+
+typedef struct ctf_type_v1
+{
+  uint32_t ctt_name;		/* Reference to name in string table.  */
+  unsigned short ctt_info;	/* Encoded kind, variant length (see below).  */
+#ifndef __GNUC__
+  union
+  {
+    unsigned short _size;	/* Always CTF_LSIZE_SENT_V1.  */
+    unsigned short _type;	/* Do not use.  */
+  } _u;
+#else
+  __extension__
+  union
+  {
+    unsigned short ctt_size;	/* Always CTF_LSIZE_SENT_V1.  */
+    unsigned short ctt_type;	/* Do not use.  */
+  };
+#endif
+  uint32_t ctt_lsizehi;		/* High 32 bits of type size in bytes.  */
+  uint32_t ctt_lsizelo;		/* Low 32 bits of type size in bytes.  */
+} ctf_type_v1_t;
+
+
+typedef struct ctf_stype
+{
+  uint32_t ctt_name;		/* Reference to name in string table.  */
+  uint32_t ctt_info;		/* Encoded kind, variant length (see below).  */
+#ifndef __GNUC__
+  union
+  {
+    uint32_t _size;		/* Size of entire type in bytes.  */
+    uint32_t _type;		/* Reference to another type.  */
+  } _u;
+#else
+  __extension__
+  union
+  {
+    uint32_t ctt_size;		/* Size of entire type in bytes.  */
+    uint32_t ctt_type;		/* Reference to another type.  */
+  };
+#endif
+} ctf_stype_t;
+
+typedef struct ctf_type
+{
+  uint32_t ctt_name;		/* Reference to name in string table.  */
+  uint32_t ctt_info;		/* Encoded kind, variant length (see below).  */
+#ifndef __GNUC__
+union
+  {
+    uint32_t _size;		/* Always CTF_LSIZE_SENT.  */
+    uint32_t _type;		/* Do not use.  */
+  } _u;
+#else
+  __extension__
+  union
+  {
+    uint32_t ctt_size;		/* Always CTF_LSIZE_SENT.  */
+    uint32_t ctt_type;		/* Do not use.  */
+  };
+#endif
+  uint32_t ctt_lsizehi;		/* High 32 bits of type size in bytes.  */
+  uint32_t ctt_lsizelo;		/* Low 32 bits of type size in bytes.  */
+} ctf_type_t;
+
+#ifndef __GNUC__
+#define ctt_size _u._size	/* For fundamental types that have a size.  */
+#define ctt_type _u._type	/* For types that reference another type.  */
+#endif
+
+/* The following macros and inline functions compose and decompose values for
+   ctt_info and ctt_name, as well as other structures that contain name
+   references.  Use outside libdtrace-ctf itself is explicitly for access to CTF
+   files directly: types returned from the library will always appear to be
+   CTF_V2.
+
+   v1: (transparently upgraded to v2 at open time: may be compiled out of the
+   library)
+               ------------------------
+   ctt_info:   | kind | isroot | vlen |
+               ------------------------
+               15   11    10    9     0
+
+   v2:
+               ------------------------
+   ctt_info:   | kind | isroot | vlen |
+               ------------------------
+               31    26    25  24     0
+
+   CTF_V1 and V2 _INFO_VLEN have the same interface:
+
+   kind = CTF_*_INFO_KIND(c.ctt_info);     <-- CTF_K_* value (see below)
+   vlen = CTF_*_INFO_VLEN(fp, c.ctt_info); <-- length of variable data list
+
+   stid = CTF_NAME_STID(c.ctt_name);     <-- string table id number (0 or 1)
+   offset = CTF_NAME_OFFSET(c.ctt_name); <-- string table byte offset
+
+   c.ctt_info = CTF_TYPE_INFO(kind, vlen);
+   c.ctt_name = CTF_TYPE_NAME(stid, offset);  */
+
+# define CTF_V1_INFO_KIND(info)		(((info) & 0xf800) >> 11)
+# define CTF_V1_INFO_ISROOT(info)	(((info) & 0x0400) >> 10)
+# define CTF_V1_INFO_VLEN(info)		(((info) & CTF_MAX_VLEN_V1))
+
+#define CTF_V2_INFO_KIND(info)		(((info) & 0xfc000000) >> 26)
+#define CTF_V2_INFO_ISROOT(info)	(((info) & 0x2000000) >> 25)
+#define CTF_V2_INFO_VLEN(info)		(((info) & CTF_MAX_VLEN))
+
+#define CTF_NAME_STID(name)		((name) >> 31)
+#define CTF_NAME_OFFSET(name)		((name) & CTF_MAX_NAME)
+
+/* V2 only. */
+#define CTF_TYPE_INFO(kind, isroot, vlen) \
+	(((kind) << 26) | (((isroot) ? 1 : 0) << 25) | ((vlen) & CTF_MAX_VLEN))
+
+#define CTF_TYPE_NAME(stid, offset) \
+	(((stid) << 31) | ((offset) & CTF_MAX_NAME))
+
+/* The next set of macros are for public consumption only.  Not used internally,
+   since the relevant type boundary is dependent upon the version of the file at
+   *opening* time, not the version after transparent upgrade.  Use
+   ctf_type_isparent() / ctf_type_ischild() for that.  */
+
+#define CTF_V2_TYPE_ISPARENT(fp, id)	((id) <= CTF_MAX_PTYPE)
+#define CTF_V2_TYPE_ISCHILD(fp, id)	((id) > CTF_MAX_PTYPE)
+#define CTF_V2_TYPE_TO_INDEX(id)	((id) & CTF_MAX_PTYPE)
+#define CTF_V2_INDEX_TO_TYPE(id, child) ((child) ? ((id) | (CTF_MAX_PTYPE+1)) : (id))
+
+# define CTF_V1_TYPE_ISPARENT(fp, id)	((id) <= CTF_MAX_PTYPE_V1)
+# define CTF_V1_TYPE_ISCHILD(fp, id)	((id) > CTF_MAX_PTYPE_V1)
+# define CTF_V1_TYPE_TO_INDEX(id)	((id) & CTF_MAX_PTYPE_V1)
+# define CTF_V1_INDEX_TO_TYPE(id, child) ((child) ? ((id) | (CTF_MAX_PTYPE_V1+1)) : (id))
+
+/* Valid for both V1 and V2. */
+#define CTF_TYPE_LSIZE(cttp) \
+	(((uint64_t)(cttp)->ctt_lsizehi) << 32 | (cttp)->ctt_lsizelo)
+#define CTF_SIZE_TO_LSIZE_HI(size)	((uint32_t)((uint64_t)(size) >> 32))
+#define CTF_SIZE_TO_LSIZE_LO(size)	((uint32_t)(size))
+
+#define CTF_STRTAB_0	0	/* String table id 0 (in-CTF).  */
+#define CTF_STRTAB_1	1	/* String table id 1 (ELF strtab).  */
+
+/* Values for CTF_TYPE_KIND().  If the kind has an associated data list,
+   CTF_INFO_VLEN() will extract the number of elements in the list, and
+   the type of each element is shown in the comments below. */
+
+#define CTF_K_UNKNOWN	0	/* Unknown type (used for padding).  */
+#define CTF_K_INTEGER	1	/* Variant data is CTF_INT_DATA (see below).  */
+#define CTF_K_FLOAT	2	/* Variant data is CTF_FP_DATA (see below).  */
+#define CTF_K_POINTER	3	/* ctt_type is referenced type.  */
+#define CTF_K_ARRAY	4	/* Variant data is single ctf_array_t.  */
+#define CTF_K_FUNCTION	5	/* ctt_type is return type, variant data is
+				   list of argument types (unsigned short's for v1,
+				   uint32_t's for v2).  */
+#define CTF_K_STRUCT	6	/* Variant data is list of ctf_member_t's.  */
+#define CTF_K_UNION	7	/* Variant data is list of ctf_member_t's.  */
+#define CTF_K_ENUM	8	/* Variant data is list of ctf_enum_t's.  */
+#define CTF_K_FORWARD	9	/* No additional data; ctt_name is tag.  */
+#define CTF_K_TYPEDEF	10	/* ctt_type is referenced type.  */
+#define CTF_K_VOLATILE	11	/* ctt_type is base type.  */
+#define CTF_K_CONST	12	/* ctt_type is base type.  */
+#define CTF_K_RESTRICT	13	/* ctt_type is base type.  */
+#define CTF_K_SLICE	14	/* Variant data is a ctf_slice_t.  */
+
+#define CTF_K_MAX	63	/* Maximum possible (V2) CTF_K_* value.  */
+
+/* Values for ctt_type when kind is CTF_K_INTEGER.  The flags, offset in bits,
+   and size in bits are encoded as a single word using the following macros.
+   (However, you can also encode the offset and bitness in a slice.)  */
+
+#define CTF_INT_ENCODING(data) (((data) & 0xff000000) >> 24)
+#define CTF_INT_OFFSET(data)   (((data) & 0x00ff0000) >> 16)
+#define CTF_INT_BITS(data)     (((data) & 0x0000ffff))
+
+#define CTF_INT_DATA(encoding, offset, bits) \
+       (((encoding) << 24) | ((offset) << 16) | (bits))
+
+#define CTF_INT_SIGNED	0x01	/* Integer is signed (otherwise unsigned).  */
+#define CTF_INT_CHAR	0x02	/* Character display format.  */
+#define CTF_INT_BOOL	0x04	/* Boolean display format.  */
+#define CTF_INT_VARARGS	0x08	/* Varargs display format.  */
+
+/* Use CTF_CHAR to produce a char that agrees with the system's native
+   char signedness.  */
+#if CHAR_MIN == 0
+# define CTF_CHAR (CTF_INT_CHAR)
+#else
+# define CTF_CHAR (CTF_INT_CHAR | CTF_INT_SIGNED)
+#endif
+
+/* Values for ctt_type when kind is CTF_K_FLOAT.  The encoding, offset in bits,
+   and size in bits are encoded as a single word using the following macros.
+   (However, you can also encode the offset and bitness in a slice.)  */
+
+#define CTF_FP_ENCODING(data)  (((data) & 0xff000000) >> 24)
+#define CTF_FP_OFFSET(data)    (((data) & 0x00ff0000) >> 16)
+#define CTF_FP_BITS(data)      (((data) & 0x0000ffff))
+
+#define CTF_FP_DATA(encoding, offset, bits) \
+       (((encoding) << 24) | ((offset) << 16) | (bits))
+
+/* Variant data when kind is CTF_K_FLOAT is an encoding in the top eight bits.  */
+#define CTF_FP_ENCODING(data)	(((data) & 0xff000000) >> 24)
+
+#define CTF_FP_SINGLE	1	/* IEEE 32-bit float encoding.  */
+#define CTF_FP_DOUBLE	2	/* IEEE 64-bit float encoding.  */
+#define CTF_FP_CPLX	3	/* Complex encoding.  */
+#define CTF_FP_DCPLX	4	/* Double complex encoding.  */
+#define CTF_FP_LDCPLX	5	/* Long double complex encoding.  */
+#define CTF_FP_LDOUBLE	6	/* Long double encoding.  */
+#define CTF_FP_INTRVL	7	/* Interval (2x32-bit) encoding.  */
+#define CTF_FP_DINTRVL	8	/* Double interval (2x64-bit) encoding.  */
+#define CTF_FP_LDINTRVL	9	/* Long double interval (2x128-bit) encoding.  */
+#define CTF_FP_IMAGRY	10	/* Imaginary (32-bit) encoding.  */
+#define CTF_FP_DIMAGRY	11	/* Long imaginary (64-bit) encoding.  */
+#define CTF_FP_LDIMAGRY	12	/* Long double imaginary (128-bit) encoding.  */
+
+#define CTF_FP_MAX	12	/* Maximum possible CTF_FP_* value */
+
+/* A slice increases the offset and reduces the bitness of the referenced
+   ctt_type, which must be a type which has an encoding (fp, int, or enum).  We
+   also store the referenced type in here, because it is easier to keep the
+   ctt_size correct for the slice than to shuffle the size into here and keep
+   the ctt_type where it is for other types.  */
+
+typedef struct ctf_slice
+{
+  uint32_t cts_type;
+  unsigned char cts_offset;
+  unsigned char cts_bits;
+} ctf_slice_t;
+
+typedef struct ctf_array_v1
+{
+  unsigned short cta_contents;	/* Reference to type of array contents.  */
+  unsigned short cta_index;	/* Reference to type of array index.  */
+  uint32_t cta_nelems;		/* Number of elements.  */
+} ctf_array_v1_t;
+
+typedef struct ctf_array
+{
+  uint32_t cta_contents;	/* Reference to type of array contents.  */
+  uint32_t cta_index;		/* Reference to type of array index.  */
+  uint32_t cta_nelems;		/* Number of elements.  */
+} ctf_array_t;
+
+/* Most structure members have bit offsets that can be expressed using a short.
+   Some don't.  ctf_member_t is used for structs which cannot contain any of
+   these large offsets, whereas ctf_lmember_t is used in the latter case.  If
+   any member of a given struct has an offset that cannot be expressed using a
+   uint32_t, all members will be stored as type ctf_lmember_t.  This is expected
+   to be very rare (but nonetheless possible).  */
+
+#define CTF_LSTRUCT_THRESH	536870912
+
+/* In v1, the same is true, except that lmembers are used for structs >= 8192
+   bytes in size.  (The ordering of members in the ctf_member_* structures is
+   different to improve padding.)  */
+
+#define CTF_LSTRUCT_THRESH_V1	8192
+
+typedef struct ctf_member_v1
+{
+  uint32_t ctm_name;		/* Reference to name in string table.  */
+  unsigned short ctm_type;	/* Reference to type of member.  */
+  unsigned short ctm_offset;	/* Offset of this member in bits.  */
+} ctf_member_v1_t;
+
+typedef struct ctf_lmember_v1
+{
+  uint32_t ctlm_name;		/* Reference to name in string table.  */
+  unsigned short ctlm_type;	/* Reference to type of member.  */
+  unsigned short ctlm_pad;	/* Padding.  */
+  uint32_t ctlm_offsethi;	/* High 32 bits of member offset in bits.  */
+  uint32_t ctlm_offsetlo;	/* Low 32 bits of member offset in bits.  */
+} ctf_lmember_v1_t;
+
+typedef struct ctf_member_v2
+{
+  uint32_t ctm_name;		/* Reference to name in string table.  */
+  uint32_t ctm_offset;		/* Offset of this member in bits.  */
+  uint32_t ctm_type;		/* Reference to type of member.  */
+} ctf_member_t;
+
+typedef struct ctf_lmember_v2
+{
+  uint32_t ctlm_name;		/* Reference to name in string table.  */
+  uint32_t ctlm_offsethi;	/* High 32 bits of member offset in bits.  */
+  uint32_t ctlm_type;		/* Reference to type of member.  */
+  uint32_t ctlm_offsetlo;	/* Low 32 bits of member offset in bits.  */
+} ctf_lmember_t;
+
+#define	CTF_LMEM_OFFSET(ctlmp) \
+	(((uint64_t)(ctlmp)->ctlm_offsethi) << 32 | (ctlmp)->ctlm_offsetlo)
+#define	CTF_OFFSET_TO_LMEMHI(offset)	((uint32_t)((uint64_t)(offset) >> 32))
+#define	CTF_OFFSET_TO_LMEMLO(offset)	((uint32_t)(offset))
+
+typedef struct ctf_enum
+{
+  uint32_t cte_name;		/* Reference to name in string table.  */
+  int cte_value;		/* Value associated with this name.  */
+} ctf_enum_t;
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif				/* _CTF_H */
-- 
2.21.0.237.gd0cfaa883d

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v2 19/19] binutils: CTF support for objdump and readelf
  2019-05-17 22:10 [PATCH v2 00/19] libctf, and CTF support for objdump and readelf Nick Alcock
                   ` (6 preceding siblings ...)
  2019-05-17 22:10 ` [PATCH v2 06/19] libctf: hashing Nick Alcock
@ 2019-05-17 22:10 ` Nick Alcock
  2019-05-17 22:10 ` [PATCH v2 15/19] libctf: mmappable archives Nick Alcock
                   ` (12 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nick Alcock @ 2019-05-17 22:10 UTC (permalink / raw)
  To: binutils

This introduces CTF support for objdump and readelf, with the same
syntax for both:

     --ctf=SECTION: display CTF in the given SECTION
     --ctf-symbols=SECTION: name of symbol table section (optional)
     --ctf-strings=SECTION: name of string table section (optional)
     --ctf-parent=SECTION: name of CTF section that is the parent of this section

Nearly all the work is done by the ctf_dump machinery in libctf: most of
the remaining work is option-processing and section-reading, and thus is
different for objdump and readelf: the minimal amount of similar code
remaining is, in my view, too small to share.

I am not particularly satisfied with the way resources are freed in
either of these (I was forced to do it at the top level, for lack of
anywhere else to free resources allocated during option processing), but
I can't see any better way to do it without introducing new
infrastructure for no other purpose.

There are essentially arbitrary ordering changes to the Makefile.in's
order of libtool-related stuff that I can't get rid of, but they have no
semantic effect.  (It is possible that some hunks of these changes could
be dropped, but that seems a bit risky to me.)

Changes from v1:
 - None!

binutils/
	* objdump.c (ctf-api.h): New include.
	(dump_ctf_section_info): New variable.
	(dump_ctf_section_name): Likewise.
	(dump_ctf_symtab_name): Likewise.
	(dump_ctf_strtab_name): Likewise.
	(usage): Describe new options.
	(enum option_values): Add OPTION_CTF,
	OPTION_CTF_SYMBOLS, OPTION_CTF_STRINGS, and OPTION_CTF_PARENT.
	(main): Use them to add --ctf, --ctf-symbols, --ctf-strings, and
	--ctf-parent.
	(read_section_stabs): Add new parameter, entsize_ptr.
	(find_stabs_section): Adjust accordingly.
	(dump_ctf_indent_lines): New.
	(dump_ctf): New.
	(dump_bfd): Call it.  Free resources afterwards.
	* readelf.c (ctf-api.h): New include.
	(CTF_DUMP): New.
	(static bfd_boolean do_ctf): Likewise.
	(dump_ctf_parent_name): Likewise.
	(dump_ctf_symtab_name): Likewise.
	(dump_ctf_strtab_name): Likewise.
	(OPTION_CTF_DUMP): Likewise.
	(OPTION_CTF_PARENT): Likewise.
	(OPTION_CTF_SYMBOLS): Likewise.
	(OPTION_CTF_STRINGS): Likewise.
	(options): Add them.
	(usage): Likewise.
	(parse_args): Handle the new options, requesting CTF_DUMP.
	(process_section_contents): Handle CTF_DUMP.
	(shdr_to_ctf_sect): New.
	(dump_ctf_indent_lines): New.
	(dump_section_as_ctf): New.
	(main): Free resources.
	* Makefile.am (LIBCTF): New variable.
	(objdump_DEPENDENCIES): Use it.
	(readelf_DEPENDENCIES): Likewise.
	(objdump_LDADD): Likewise.
	(readelf_LDADD): Likewise.
	* aclocal.m4: Regenerated.
	* Makefile.in: Likewise.

	* doc/binutils.texi (objdump): Document the new options.
	(readelf): Likewise.
	* doc/ctf.options.texi: New.
	* doc/Makefile.in: Regenerated.
---
 binutils/Makefile.am          |  10 +-
 binutils/Makefile.in          |  18 +--
 binutils/aclocal.m4           |  10 +-
 binutils/doc/Makefile.in      |   9 +-
 binutils/doc/binutils.texi    |  12 ++
 binutils/doc/ctf.options.texi |  19 ++++
 binutils/objdump.c            | 156 ++++++++++++++++++++++++-
 binutils/readelf.c            | 206 ++++++++++++++++++++++++++++++++++
 8 files changed, 414 insertions(+), 26 deletions(-)
 create mode 100644 binutils/doc/ctf.options.texi

diff --git a/binutils/Makefile.am b/binutils/Makefile.am
index 7d59d8c4b5..128494ca9e 100644
--- a/binutils/Makefile.am
+++ b/binutils/Makefile.am
@@ -161,6 +161,8 @@ BFDLIB = ../bfd/libbfd.la
 
 OPCODES = ../opcodes/libopcodes.la
 
+LIBCTF = ../libctf/libctf.a
+
 LIBIBERTY = ../libiberty/libiberty.a
 
 POTFILES = $(CFILES) $(DEBUG_SRCS) $(HFILES)
@@ -211,7 +213,7 @@ installcheck-local:
 # which depends on libintl, since we don't know whether LIBINTL_DEP will be
 # non-empty until configure time.  Ugh!
 size_DEPENDENCIES =      $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB)
-objdump_DEPENDENCIES =   $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) $(OPCODES) $(OBJDUMP_PRIVATE_OFILES)
+objdump_DEPENDENCIES =   $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) $(OPCODES) $(LIBCTF) $(OBJDUMP_PRIVATE_OFILES)
 nm_new_DEPENDENCIES =    $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB)
 ar_DEPENDENCIES =        $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB)
 strings_DEPENDENCIES =   $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB)
@@ -226,7 +228,7 @@ dlltool_DEPENDENCIES =   $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB)
 windres_DEPENDENCIES =   $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB)
 windmc_DEPENDENCIES =    $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB)
 addr2line_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB)
-readelf_DEPENDENCIES =   $(LIBINTL_DEP) $(LIBIBERTY)
+readelf_DEPENDENCIES =   $(LIBINTL_DEP) $(LIBIBERTY) $(LIBCTF)
 elfedit_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY)
 dllwrap_DEPENDENCIES =   $(LIBINTL_DEP) $(LIBIBERTY)
 bfdtest1_DEPENDENCIES =  $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB)
@@ -241,7 +243,7 @@ objcopy_SOURCES = objcopy.c not-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS)
 strings_SOURCES = strings.c $(BULIBS)
 
 readelf_SOURCES = readelf.c version.c unwind-ia64.c dwarf.c $(ELFLIBS)
-readelf_LDADD   = $(LIBINTL) $(LIBIBERTY) $(ZLIB)
+readelf_LDADD   = $(LIBINTL) $(LIBCTF) $(LIBIBERTY) $(ZLIB)
 
 elfedit_SOURCES = elfedit.c version.c $(ELFLIBS)
 elfedit_LDADD = $(LIBINTL) $(LIBIBERTY)
@@ -252,7 +254,7 @@ nm_new_SOURCES = nm.c $(BULIBS)
 
 objdump_SOURCES = objdump.c dwarf.c prdbg.c $(DEBUG_SRCS) $(BULIBS) $(ELFLIBS)
 EXTRA_objdump_SOURCES = od-xcoff.c
-objdump_LDADD = $(OBJDUMP_PRIVATE_OFILES) $(OPCODES) $(BFDLIB) $(LIBIBERTY) $(LIBINTL)
+objdump_LDADD = $(OBJDUMP_PRIVATE_OFILES) $(OPCODES) $(LIBCTF) $(BFDLIB) $(LIBIBERTY) $(LIBINTL)
 
 objdump.@OBJEXT@:objdump.c
 if am__fastdepCC
diff --git a/binutils/Makefile.in b/binutils/Makefile.in
index f6cb22f95a..480385bd67 100644
--- a/binutils/Makefile.in
+++ b/binutils/Makefile.in
@@ -119,7 +119,10 @@ EXTRA_PROGRAMS = srconv$(EXEEXT) sysdump$(EXEEXT) coffdump$(EXEEXT) \
 	$(am__EXEEXT_4)
 subdir = .
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/../bfd/acinclude.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/../libtool.m4 \
+	$(top_srcdir)/../ltoptions.m4 $(top_srcdir)/../ltsugar.m4 \
+	$(top_srcdir)/../ltversion.m4 $(top_srcdir)/../lt~obsolete.m4 \
+	$(top_srcdir)/../bfd/acinclude.m4 \
 	$(top_srcdir)/../bfd/warning.m4 $(top_srcdir)/../config/acx.m4 \
 	$(top_srcdir)/../config/depstand.m4 \
 	$(top_srcdir)/../config/gettext-sister.m4 \
@@ -135,9 +138,7 @@ am__aclocal_m4_deps = $(top_srcdir)/../bfd/acinclude.m4 \
 	$(top_srcdir)/../config/plugins.m4 \
 	$(top_srcdir)/../config/po.m4 \
 	$(top_srcdir)/../config/progtest.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)/../config/zlib.m4 \
 	$(top_srcdir)/../bfd/version.m4 $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
@@ -647,6 +648,7 @@ BULIBS = bucomm.c version.c filemode.c
 ELFLIBS = elfcomm.c
 BFDLIB = ../bfd/libbfd.la
 OPCODES = ../opcodes/libopcodes.la
+LIBCTF = ../libctf/libctf.a
 LIBIBERTY = ../libiberty/libiberty.a
 POTFILES = $(CFILES) $(DEBUG_SRCS) $(HFILES)
 EXPECT = expect
@@ -671,7 +673,7 @@ CC_FOR_TARGET = ` \
 # which depends on libintl, since we don't know whether LIBINTL_DEP will be
 # non-empty until configure time.  Ugh!
 size_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB)
-objdump_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) $(OPCODES) $(OBJDUMP_PRIVATE_OFILES)
+objdump_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) $(OPCODES) $(LIBCTF) $(OBJDUMP_PRIVATE_OFILES)
 nm_new_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB)
 ar_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB)
 strings_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB)
@@ -686,7 +688,7 @@ dlltool_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB)
 windres_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB)
 windmc_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB)
 addr2line_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB)
-readelf_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY)
+readelf_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(LIBCTF)
 elfedit_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY)
 dllwrap_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY)
 bfdtest1_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB)
@@ -696,14 +698,14 @@ size_SOURCES = size.c $(BULIBS)
 objcopy_SOURCES = objcopy.c not-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS)
 strings_SOURCES = strings.c $(BULIBS)
 readelf_SOURCES = readelf.c version.c unwind-ia64.c dwarf.c $(ELFLIBS)
-readelf_LDADD = $(LIBINTL) $(LIBIBERTY) $(ZLIB)
+readelf_LDADD = $(LIBINTL) $(LIBCTF) $(LIBIBERTY) $(ZLIB)
 elfedit_SOURCES = elfedit.c version.c $(ELFLIBS)
 elfedit_LDADD = $(LIBINTL) $(LIBIBERTY)
 strip_new_SOURCES = objcopy.c is-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS)
 nm_new_SOURCES = nm.c $(BULIBS)
 objdump_SOURCES = objdump.c dwarf.c prdbg.c $(DEBUG_SRCS) $(BULIBS) $(ELFLIBS)
 EXTRA_objdump_SOURCES = od-xcoff.c
-objdump_LDADD = $(OBJDUMP_PRIVATE_OFILES) $(OPCODES) $(BFDLIB) $(LIBIBERTY) $(LIBINTL)
+objdump_LDADD = $(OBJDUMP_PRIVATE_OFILES) $(OPCODES) $(LIBCTF) $(BFDLIB) $(LIBIBERTY) $(LIBINTL)
 cxxfilt_SOURCES = cxxfilt.c $(BULIBS)
 ar_SOURCES = arparse.y arlex.l ar.c not-ranlib.c arsup.c rename.c binemul.c \
 	emul_$(EMULATION).c $(BULIBS)
diff --git a/binutils/aclocal.m4 b/binutils/aclocal.m4
index 4fa32fffd8..1b1320fd1a 100644
--- a/binutils/aclocal.m4
+++ b/binutils/aclocal.m4
@@ -1185,6 +1185,11 @@ AC_SUBST([am__tar])
 AC_SUBST([am__untar])
 ]) # _AM_PROG_TAR
 
+m4_include([../libtool.m4])
+m4_include([../ltoptions.m4])
+m4_include([../ltsugar.m4])
+m4_include([../ltversion.m4])
+m4_include([../lt~obsolete.m4])
 m4_include([../bfd/acinclude.m4])
 m4_include([../bfd/warning.m4])
 m4_include([../config/acx.m4])
@@ -1203,8 +1208,3 @@ 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])
-m4_include([../ltversion.m4])
-m4_include([../lt~obsolete.m4])
diff --git a/binutils/doc/Makefile.in b/binutils/doc/Makefile.in
index a0777d8fcc..7fa622a364 100644
--- a/binutils/doc/Makefile.in
+++ b/binutils/doc/Makefile.in
@@ -108,7 +108,10 @@ host_triplet = @host@
 target_triplet = @target@
 subdir = doc
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/../bfd/acinclude.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/../libtool.m4 \
+	$(top_srcdir)/../ltoptions.m4 $(top_srcdir)/../ltsugar.m4 \
+	$(top_srcdir)/../ltversion.m4 $(top_srcdir)/../lt~obsolete.m4 \
+	$(top_srcdir)/../bfd/acinclude.m4 \
 	$(top_srcdir)/../bfd/warning.m4 $(top_srcdir)/../config/acx.m4 \
 	$(top_srcdir)/../config/depstand.m4 \
 	$(top_srcdir)/../config/gettext-sister.m4 \
@@ -124,9 +127,7 @@ am__aclocal_m4_deps = $(top_srcdir)/../bfd/acinclude.m4 \
 	$(top_srcdir)/../config/plugins.m4 \
 	$(top_srcdir)/../config/po.m4 \
 	$(top_srcdir)/../config/progtest.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)/../config/zlib.m4 \
 	$(top_srcdir)/../bfd/version.m4 $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi
index 01f1e5f56d..e66dc4dbb1 100644
--- a/binutils/doc/binutils.texi
+++ b/binutils/doc/binutils.texi
@@ -2104,6 +2104,7 @@ objdump [@option{-a}|@option{--archive-headers}]
         [@option{-s}|@option{--full-contents}]
         [@option{-W[lLiaprmfFsoRtUuTgAckK]}|
          @option{--dwarf}[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=loc,=Ranges,=pubtypes,=trace_info,=trace_abbrev,=trace_aranges,=gdb_index,=addr,=cu_index,=links,=follow-links]]
+        [@option{--ctf=}@var{section}]
         [@option{-G}|@option{--stabs}]
         [@option{-t}|@option{--syms}]
         [@option{-T}|@option{--dynamic-syms}]
@@ -2116,6 +2117,9 @@ objdump [@option{-a}|@option{--archive-headers}]
         [@option{--adjust-vma=}@var{offset}]
         [@option{--dwarf-depth=@var{n}}]
         [@option{--dwarf-start=@var{n}}]
+        [@option{--ctf-parent=}@var{section}]
+        [@option{--ctf-symbols=}@var{section}]
+        [@option{--ctf-strings=}@var{section}]
         [@option{--no-recurse-limit}|@option{--recurse-limit}]
         [@option{--special-syms}]
         [@option{--prefix=}@var{prefix}]
@@ -2623,6 +2627,8 @@ instructions.
 @item --dwarf-check
 Enable additional checks for consistency of Dwarf information.
 
+@include ctf.options.texi
+
 @item -G
 @itemx --stabs
 @cindex stab
@@ -4622,6 +4628,10 @@ readelf [@option{-a}|@option{--all}]
          @option{--debug-dump}[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=loc,=Ranges,=pubtypes,=trace_info,=trace_abbrev,=trace_aranges,=gdb_index,=addr,=cu_index,=links,=follow-links]]
         [@option{--dwarf-depth=@var{n}}]
         [@option{--dwarf-start=@var{n}}]
+        [@option{--ctf=}@var{section}]
+        [@option{--ctf-parent=}@var{section}]
+        [@option{--ctf-symbols=}@var{section}]
+        [@option{--ctf-strings=}@var{section}]
         [@option{-I}|@option{--histogram}]
         [@option{-v}|@option{--version}]
         [@option{-W}|@option{--wide}]
@@ -4802,6 +4812,8 @@ command to @command{ar}, but without using the BFD library.  @xref{ar}.
 @itemx --debug-dump[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=loc,=Ranges,=pubtypes,=trace_info,=trace_abbrev,=trace_aranges,=gdb_index,=addr,=cu_index,=links,=follow-links]
 @include debug.options.texi
 
+@include ctf.options.texi
+
 @item -I
 @itemx --histogram
 Display a histogram of bucket list lengths when displaying the contents
diff --git a/binutils/doc/ctf.options.texi b/binutils/doc/ctf.options.texi
new file mode 100644
index 0000000000..d9e49e4b7e
--- /dev/null
+++ b/binutils/doc/ctf.options.texi
@@ -0,0 +1,19 @@
+@c This file contains the entry for the --ctf, --ctf-parent, --ctf-symbols, -and
+@c --ctf-strings options that are common to both readelf and objdump.
+
+@item --ctf=@var{section}
+@cindex CTF
+@cindex Compact Type Format
+
+Display the contents of the specified CTF section.  CTF sections themselves
+contain many subsections, all of which are displayed in order.
+
+@item --ctf-parent=@var{section}
+@item --ctf-symbols=@var{section}
+@item --ctf-strings=@var{section}
+
+Specify the names of other sections from which the CTF file can inherit
+types, strings, and symbols.
+
+If either of @option{--ctf-symbols} or @option{--ctf-strings} is specified, the
+other must be specified as well.
diff --git a/binutils/objdump.c b/binutils/objdump.c
index 872539068c..adb029729a 100644
--- a/binutils/objdump.c
+++ b/binutils/objdump.c
@@ -56,6 +56,7 @@
 #include "bucomm.h"
 #include "elfcomm.h"
 #include "dwarf.h"
+#include "ctf-api.h"
 #include "getopt.h"
 #include "safe-ctype.h"
 #include "dis-asm.h"
@@ -98,6 +99,11 @@ static bfd_boolean with_source_code;	/* -S */
 static int show_raw_insn;		/* --show-raw-insn */
 static int dump_dwarf_section_info;	/* --dwarf */
 static int dump_stab_section_info;	/* --stabs */
+static int dump_ctf_section_info;       /* --ctf */
+static char *dump_ctf_section_name;
+static char *dump_ctf_symtab_name;	/* --ctf-symbols */
+static char *dump_ctf_strtab_name;	/* --ctf-strings */
+static char *dump_ctf_parent_name;	/* --ctf-parent */
 static int do_demangle;			/* -C, --demangle */
 static bfd_boolean disassemble;		/* -d */
 static bfd_boolean disassemble_all;	/* -D */
@@ -225,6 +231,7 @@ usage (FILE *stream, int status)
           =gdb_index,=trace_info,=trace_abbrev,=trace_aranges,\n\
           =addr,=cu_index,=links,=follow-links]\n\
                            Display DWARF info in the file\n\
+  --ctf=SECTION            Display CTF info from SECTION\n\
   -t, --syms               Display the contents of the symbol table(s)\n\
   -T, --dynamic-syms       Display the contents of the dynamic symbol table\n\
   -r, --reloc              Display the relocation entries in the file\n\
@@ -273,7 +280,10 @@ usage (FILE *stream, int status)
       --dwarf-start=N        Display DIEs starting with N, at the same depth\n\
                              or deeper\n\
       --dwarf-check          Make additional dwarf internal consistency checks.\
-      \n\n"));
+      \n\
+      --ctf-parent=SECTION     Use SECTION as the CTF parent\n\
+      --ctf-symbols=SECTION    Use SECTION as the CTF external symbol table\n\
+      --ctf-strings=SECTION    Use SECTION as the CTF external string table\n\n"));
       list_supported_targets (program_name, stream);
       list_supported_architectures (program_name, stream);
 
@@ -308,7 +318,11 @@ enum option_values
     OPTION_DWARF_START,
     OPTION_RECURSE_LIMIT,
     OPTION_NO_RECURSE_LIMIT,
-    OPTION_INLINES
+    OPTION_INLINES,
+    OPTION_CTF,
+    OPTION_CTF_SYMBOLS,
+    OPTION_CTF_STRINGS,
+    OPTION_CTF_PARENT
   };
 
 static struct option long_options[]=
@@ -351,6 +365,10 @@ static struct option long_options[]=
   {"special-syms", no_argument, &dump_special_syms, 1},
   {"include", required_argument, NULL, 'I'},
   {"dwarf", optional_argument, NULL, OPTION_DWARF},
+  {"ctf", required_argument, NULL, OPTION_CTF},
+  {"ctf-symbols", required_argument, NULL, OPTION_CTF_SYMBOLS},
+  {"ctf-strings", required_argument, NULL, OPTION_CTF_STRINGS},
+  {"ctf-parent", required_argument, NULL, OPTION_CTF_PARENT},
   {"stabs", no_argument, NULL, 'G'},
   {"start-address", required_argument, NULL, OPTION_START_ADDRESS},
   {"stop-address", required_argument, NULL, OPTION_STOP_ADDRESS},
@@ -2960,7 +2978,8 @@ dump_dwarf (bfd *abfd)
    it.  Return NULL on failure.   */
 
 static bfd_byte *
-read_section_stabs (bfd *abfd, const char *sect_name, bfd_size_type *size_ptr)
+read_section_stabs (bfd *abfd, const char *sect_name, bfd_size_type *size_ptr,
+		    bfd_size_type *entsize_ptr)
 {
   asection *stabsect;
   bfd_byte *contents;
@@ -2984,6 +3003,8 @@ read_section_stabs (bfd *abfd, const char *sect_name, bfd_size_type *size_ptr)
     }
 
   *size_ptr = bfd_section_size (abfd, stabsect);
+  if (entsize_ptr)
+    *entsize_ptr = stabsect->entsize;
 
   return contents;
 }
@@ -3107,11 +3128,11 @@ find_stabs_section (bfd *abfd, asection *section, void *names)
     {
       if (strtab == NULL)
 	strtab = read_section_stabs (abfd, sought->string_section_name,
-				     &stabstr_size);
+				     &stabstr_size, NULL);
 
       if (strtab)
 	{
-	  stabs = read_section_stabs (abfd, section->name, &stab_size);
+	  stabs = read_section_stabs (abfd, section->name, &stab_size, NULL);
 	  if (stabs)
 	    print_section_stabs (abfd, section->name, &sought->string_offset);
 	}
@@ -3173,6 +3194,110 @@ dump_bfd_header (bfd *abfd)
   bfd_printf_vma (abfd, abfd->start_address);
   printf ("\n");
 }
+\f
+
+/* Formatting callback function passed to ctf_dump.  Returns either the pointer
+   it is passed, or a pointer to newly-allocated storage, in which case
+   dump_ctf() will free it when it no longer needs it.  */
+
+static char *dump_ctf_indent_lines (ctf_sect_names_t sect ATTRIBUTE_UNUSED,
+				    char *s, void *arg)
+{
+  char *spaces = arg;
+  char *new_s;
+
+  if (asprintf (&new_s, "%s%s", spaces, s) < 0)
+    return s;
+  return new_s;
+}
+
+/* Dump the CTF debugging information.  */
+
+static void
+dump_ctf (bfd *abfd, const char *sect_name, const char *symtab_name,
+	  const char *strtab_name, const char *parent_name)
+{
+  bfd_byte *ctfdata, *symdata = NULL, *strdata = NULL, *parentdata = NULL;
+  bfd_size_type ctfsize, symsize, symentsize, strsize, parentsize;
+  ctf_file_t *ctf;
+  ctf_file_t *parent = NULL;
+  const char *things[] = {"Labels", "Data objects", "Function objects",
+			  "Variables", "Types", "Strings", ""};
+  const char **thing;
+  int err;
+  size_t i;
+
+  if ((ctfdata = read_section_stabs (abfd, sect_name, &ctfsize, NULL)) == NULL)
+      bfd_fatal (bfd_get_filename (abfd));
+
+  if (symtab_name
+      && (symdata = read_section_stabs (abfd, symtab_name, &symsize,
+					&symentsize)) == NULL)
+    bfd_fatal (bfd_get_filename (abfd));
+
+  if (strtab_name
+      && (strdata = read_section_stabs (abfd, strtab_name, &strsize,
+					NULL)) == NULL)
+    bfd_fatal (bfd_get_filename (abfd));
+
+  if (parent_name
+      && (parentdata = read_section_stabs (abfd, parent_name, &parentsize,
+					   NULL)) == NULL)
+    bfd_fatal (bfd_get_filename (abfd));
+
+  /* Load the CTF file and dump it.  */
+
+  if ((ctf = ctf_simple_open ((void *) ctfdata, ctfsize,
+			      (void *) symdata, symsize, symentsize,
+			      (void *) strdata, strsize, &err)) == NULL)
+    {
+      non_fatal (_("CTF open failure: %s\n"), ctf_errmsg (err));
+      bfd_fatal (bfd_get_filename (abfd));
+    }
+
+  if (parentdata)
+    {
+      if ((parent = ctf_simple_open ((void *) parentdata, parentsize,
+				     (void *) symdata, symsize, symentsize,
+				     (void *) strdata, strsize, &err)) == NULL)
+	{
+	  non_fatal (_("CTF open failure: %s\n"), ctf_errmsg (err));
+	  bfd_fatal (bfd_get_filename (abfd));
+	}
+
+      ctf_import (ctf, parent);
+    }
+
+  printf (_("Contents of CTF section %s:\n"), sanitize_string (sect_name));
+
+  for (i = 1, thing = things; *thing[0]; thing++, i++)
+    {
+      ctf_dump_state_t *s = NULL;
+      char *item;
+
+      printf ("\n  %s:\n", *thing);
+      while ((item = ctf_dump (ctf, &s, i, dump_ctf_indent_lines,
+			       (void *) "    ")) != NULL)
+	{
+	  printf ("%s\n", item);
+	  free (item);
+	}
+
+      if (ctf_errno (ctf))
+	{
+	  non_fatal (_("Iteration failed: %s, %s\n"), *thing,
+		   ctf_errmsg (ctf_errno (ctf)));
+	  break;
+	}
+    }
+
+  ctf_close (ctf);
+  ctf_close (parent);
+  free (parentdata);
+  free (symdata);
+  free (strdata);
+  free (ctfdata);
+}
 
 \f
 static void
@@ -3812,6 +3937,9 @@ dump_bfd (bfd *abfd)
     dump_symbols (abfd, TRUE);
   if (dump_dwarf_section_info)
     dump_dwarf (abfd);
+  if (dump_ctf_section_info)
+    dump_ctf (abfd, dump_ctf_section_name, dump_ctf_symtab_name,
+	      dump_ctf_strtab_name, dump_ctf_parent_name);
   if (dump_stab_section_info)
     dump_stabs (abfd);
   if (dump_reloc_info && ! disassemble)
@@ -4248,6 +4376,20 @@ main (int argc, char **argv)
 	case OPTION_DWARF_CHECK:
 	  dwarf_check = TRUE;
 	  break;
+        case OPTION_CTF:
+          dump_ctf_section_info = TRUE;
+          dump_ctf_section_name = xstrdup (optarg);
+          seenflag = TRUE;
+          break;
+	case OPTION_CTF_SYMBOLS:
+	  dump_ctf_symtab_name = xstrdup (optarg);
+	  break;
+	case OPTION_CTF_STRINGS:
+	  dump_ctf_strtab_name = xstrdup (optarg);
+	  break;
+	case OPTION_CTF_PARENT:
+	  dump_ctf_parent_name = xstrdup (optarg);
+	  break;
 	case 'G':
 	  dump_stab_section_info = TRUE;
 	  seenflag = TRUE;
@@ -4307,6 +4449,10 @@ main (int argc, char **argv)
     }
 
   free_only_list ();
+  free (dump_ctf_section_name);
+  free (dump_ctf_symtab_name);
+  free (dump_ctf_strtab_name);
+  free (dump_ctf_parent_name);
 
   END_PROGRESS (program_name);
 
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 77acc6a7b4..2a35e2c4c8 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -60,6 +60,7 @@
 #include "bucomm.h"
 #include "elfcomm.h"
 #include "dwarf.h"
+#include "ctf-api.h"
 
 #include "elf/common.h"
 #include "elf/external.h"
@@ -182,6 +183,7 @@ typedef struct elf_section_list
 #define DEBUG_DUMP	(1 << 2)	/* The -w command line switch.  */
 #define STRING_DUMP     (1 << 3)	/* The -p command line switch.  */
 #define RELOC_DUMP      (1 << 4)	/* The -R command line switch.  */
+#define CTF_DUMP        (1 << 5)        /* The --ctf command line switch.  */
 
 typedef unsigned char dump_type;
 
@@ -248,12 +250,17 @@ static bfd_boolean do_dump = FALSE;
 static bfd_boolean do_version = FALSE;
 static bfd_boolean do_histogram = FALSE;
 static bfd_boolean do_debugging = FALSE;
+static bfd_boolean do_ctf = FALSE;
 static bfd_boolean do_arch = FALSE;
 static bfd_boolean do_notes = FALSE;
 static bfd_boolean do_archive_index = FALSE;
 static bfd_boolean is_32bit_elf = FALSE;
 static bfd_boolean decompress_dumps = FALSE;
 
+static char *dump_ctf_parent_name;
+static char *dump_ctf_symtab_name;
+static char *dump_ctf_strtab_name;
+
 struct group_list
 {
   struct group_list *  next;
@@ -4371,6 +4378,10 @@ get_section_type_name (Filedata * filedata, unsigned int sh_type)
 #define OPTION_DWARF_DEPTH	514
 #define OPTION_DWARF_START	515
 #define OPTION_DWARF_CHECK	516
+#define OPTION_CTF_DUMP		517
+#define OPTION_CTF_PARENT	518
+#define OPTION_CTF_SYMBOLS	519
+#define OPTION_CTF_STRINGS	520
 
 static struct option options[] =
 {
@@ -4409,6 +4420,12 @@ static struct option options[] =
   {"dwarf-start",      required_argument, 0, OPTION_DWARF_START},
   {"dwarf-check",      no_argument, 0, OPTION_DWARF_CHECK},
 
+  {"ctf",              required_argument, 0, OPTION_CTF_DUMP},
+
+  {"ctf-symbols",      required_argument, 0, OPTION_CTF_SYMBOLS},
+  {"ctf-strings",      required_argument, 0, OPTION_CTF_STRINGS},
+  {"ctf-parent",       required_argument, 0, OPTION_CTF_PARENT},
+
   {"version",	       no_argument, 0, 'v'},
   {"wide",	       no_argument, 0, 'W'},
   {"help",	       no_argument, 0, 'H'},
@@ -4458,6 +4475,15 @@ usage (FILE * stream)
   --dwarf-depth=N        Do not display DIEs at depth N or greater\n\
   --dwarf-start=N        Display DIEs starting with N, at the same depth\n\
                          or deeper\n"));
+  fprintf (stream, _("\
+  --ctf=<number|name>    Display CTF info from section <number|name>\n\
+  --ctf-parent=<number|name>\n\
+                         Use section <number|name> as the CTF parent\n\n\
+  --ctf-symbols=<number|name>\n\
+                         Use section <number|name> as the CTF external symtab\n\n\
+  --ctf-strings=<number|name>\n\
+                         Use section <number|name> as the CTF external strtab\n\n"));
+
 #ifdef SUPPORT_DISASSEMBLY
   fprintf (stream, _("\
   -i --instruction-dump=<number|name>\n\
@@ -4685,6 +4711,19 @@ parse_args (Filedata * filedata, int argc, char ** argv)
 	case OPTION_DWARF_CHECK:
 	  dwarf_check = TRUE;
 	  break;
+	case OPTION_CTF_DUMP:
+	  do_ctf = TRUE;
+	  request_dump (filedata, CTF_DUMP);
+	  break;
+	case OPTION_CTF_SYMBOLS:
+	  dump_ctf_symtab_name = strdup (optarg);
+	  break;
+	case OPTION_CTF_STRINGS:
+	  dump_ctf_strtab_name = strdup (optarg);
+	  break;
+	case OPTION_CTF_PARENT:
+	  dump_ctf_parent_name = strdup (optarg);
+	  break;
 	case OPTION_DYN_SYMS:
 	  do_dyn_syms = TRUE;
 	  break;
@@ -13706,6 +13745,163 @@ dump_section_as_bytes (Elf_Internal_Shdr *  section,
   return TRUE;
 }
 
+static ctf_sect_t *
+shdr_to_ctf_sect (ctf_sect_t *buf, Elf_Internal_Shdr *shdr, Filedata *filedata)
+{
+  buf->cts_name = SECTION_NAME(shdr);
+  buf->cts_type = shdr->sh_type;
+  buf->cts_flags = shdr->sh_flags;
+  buf->cts_size = shdr->sh_size;
+  buf->cts_entsize = shdr->sh_entsize;
+  buf->cts_offset = (off64_t) shdr->sh_offset;
+
+  return buf;
+}
+
+/* Formatting callback function passed to ctf_dump.  Returns either the pointer
+   it is passed, or a pointer to newly-allocated storage, in which case
+   dump_ctf() will free it when it no longer needs it.  */
+
+static char *dump_ctf_indent_lines (ctf_sect_names_t sect ATTRIBUTE_UNUSED,
+				    char *s, void *arg)
+{
+  char *spaces = arg;
+  char *new_s;
+
+  if (asprintf (&new_s, "%s%s", spaces, s) < 0)
+    return s;
+  return new_s;
+}
+
+static bfd_boolean
+dump_section_as_ctf (Elf_Internal_Shdr * section, Filedata * filedata)
+{
+  Elf_Internal_Shdr *  parent_sec = NULL;
+  Elf_Internal_Shdr *  symtab_sec = NULL;
+  Elf_Internal_Shdr *  strtab_sec = NULL;
+  void *      	       data = NULL;
+  void *      	       symdata = NULL;
+  void *      	       strdata = NULL;
+  void *      	       parentdata = NULL;
+  ctf_sect_t           ctfsect, symsect, strsect, parentsect;
+  ctf_sect_t *         symsectp = NULL;
+  ctf_sect_t *         strsectp = NULL;
+  ctf_file_t *         ctf = NULL;
+  ctf_file_t *         parent = NULL;
+
+  const char *things[] = {"Labels", "Data objects", "Function objects",
+			  "Variables", "Types", "Strings", ""};
+  const char **thing;
+  int err;
+  bfd_boolean ret = FALSE;
+  size_t i;
+
+  shdr_to_ctf_sect (&ctfsect, section, filedata);
+  data = get_section_contents (section, filedata);
+  ctfsect.cts_data = data;
+
+  if (dump_ctf_symtab_name)
+    {
+      if ((symtab_sec = find_section (filedata, dump_ctf_symtab_name)) == NULL)
+	{
+	  error (_("No symbol section named %s\n"), dump_ctf_symtab_name);
+	  goto fail;
+	}
+      if ((symdata = (void *) get_data (NULL, filedata,
+					symtab_sec->sh_offset, 1,
+					symtab_sec->sh_size,
+					_("symbols"))) == NULL)
+	goto fail;
+      symsectp = shdr_to_ctf_sect (&symsect, symtab_sec, filedata);
+      symsect.cts_data = symdata;
+    }
+  if (dump_ctf_strtab_name)
+    {
+      if ((strtab_sec = find_section (filedata, dump_ctf_strtab_name)) == NULL)
+	{
+	  error (_("No string table section named %s\n"),
+		 dump_ctf_strtab_name);
+	  goto fail;
+	}
+      if ((strdata = (void *) get_data (NULL, filedata,
+					strtab_sec->sh_offset, 1,
+					strtab_sec->sh_size,
+					_("strings"))) == NULL)
+	goto fail;
+      strsectp = shdr_to_ctf_sect (&strsect, strtab_sec, filedata);
+      strsect.cts_data = strdata;
+    }
+  if (dump_ctf_parent_name)
+    {
+      if ((parent_sec = find_section (filedata, dump_ctf_parent_name)) == NULL)
+	{
+	  error (_("No CTF parent section named %s\n"), dump_ctf_parent_name);
+	  goto fail;
+	}
+      if ((parentdata = (void *) get_data (NULL, filedata,
+					   parent_sec->sh_offset, 1,
+					   parent_sec->sh_size,
+					   _("CTF parent"))) == NULL)
+	goto fail;
+      shdr_to_ctf_sect (&parentsect, parent_sec, filedata);
+      parentsect.cts_data = parentdata;
+    }
+
+  /* Load the CTF file and dump it.  */
+
+  if ((ctf = ctf_bufopen (&ctfsect, symsectp, strsectp, &err)) == NULL)
+    {
+      error (_("CTF open failure: %s\n"), ctf_errmsg (err));
+      goto fail;
+    }
+
+  if (parentdata)
+    {
+      if ((parent = ctf_bufopen (&parentsect, symsectp, strsectp, &err)) == NULL)
+	{
+	  error (_("CTF open failure: %s\n"), ctf_errmsg (err));
+	  goto fail;
+	}
+
+      ctf_import (ctf, parent);
+    }
+
+  ret = TRUE;
+
+  printf (_("\nDump of CTF section '%s':\n"),
+	  printable_section_name (filedata, section));
+
+  for (i = 1, thing = things; *thing[0]; thing++, i++)
+    {
+      ctf_dump_state_t *s = NULL;
+      char *item;
+
+      printf ("\n  %s:\n", *thing);
+      while ((item = ctf_dump (ctf, &s, i, dump_ctf_indent_lines,
+			       (void *) "    ")) != NULL)
+	{
+	  printf ("%s\n", item);
+	  free (item);
+	}
+
+      if (ctf_errno (ctf))
+	{
+	  error (_("Iteration failed: %s, %s\n"), *thing,
+		   ctf_errmsg (ctf_errno (ctf)));
+	  ret = FALSE;
+	}
+    }
+
+ fail:
+  ctf_close (ctf);
+  ctf_close (parent);
+  free (parentdata);
+  free (data);
+  free (symdata);
+  free (strdata);
+  return ret;
+}
+
 static bfd_boolean
 load_specific_debug_section (enum dwarf_section_display_enum  debug,
 			     const Elf_Internal_Shdr *        sec,
@@ -14043,6 +14239,12 @@ process_section_contents (Filedata * filedata)
 	  if (! display_debug_section (i, section, filedata))
 	    res = FALSE;
 	}
+
+      if (dump & CTF_DUMP)
+	{
+	  if (! dump_section_as_ctf (section, filedata))
+	    res = FALSE;
+	}
     }
 
   /* Check to see if the user requested a
@@ -19777,5 +19979,9 @@ main (int argc, char ** argv)
   if (cmdline.dump_sects != NULL)
     free (cmdline.dump_sects);
 
+  free (dump_ctf_symtab_name);
+  free (dump_ctf_strtab_name);
+  free (dump_ctf_parent_name);
+
   return err ? EXIT_FAILURE : EXIT_SUCCESS;
 }
-- 
2.21.0.237.gd0cfaa883d

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v2 09/19] libctf: opening
  2019-05-17 22:10 [PATCH v2 00/19] libctf, and CTF support for objdump and readelf Nick Alcock
                   ` (12 preceding siblings ...)
  2019-05-17 22:10 ` [PATCH v2 13/19] libctf: type copying Nick Alcock
@ 2019-05-17 22:10 ` Nick Alcock
  2019-05-17 22:10 ` [PATCH v2 10/19] libctf: ELF file opening via BFD Nick Alcock
                   ` (6 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nick Alcock @ 2019-05-17 22:10 UTC (permalink / raw)
  To: binutils

This fills in the other half of the opening/creation puzzle: opening of
already-existing CTF files.  Such files are always read-only: if you
want to add to a CTF file opened with one of the opening functions in
this file, use ctf_add_type(), in a later commit, to copy appropriate
types into a newly ctf_create()d, writable container.

The lowest-level opening functions are in here: ctf_bufopen(), which
takes ctf_sect_t structures akin to ELF section headers, and
ctf_simple_open(), which can be used if you don't have an entire ELF
section header to work from.  Both will malloc() new space for the
buffers only if necessary, will mmap() directly from the file if
requested, and will mprotect() it afterwards to prevent accidental
corruption of the types. These functions are also used by ctf_update()
when converting types in a writable container into read-only types that
can be looked up using the lookup functions (in later commits).

The files are always of the native endianness of the system that created
them: at read time, the endianness of the header magic number is used to
determine whether or not the file needs byte-swapping, and the entire
thing is aggressively byte-swapped.

The agggressive nature of this swapping avoids complicating the rest of
the code with endianness conversions, while the native endianness
introduces no byte-swapping overhead in the common case. (The
endianness-independence code is also much newer than everything else in
this file, and deserves closer scrutiny.)

The accessors at the top of the file are there to transparently support
older versions of the CTF file format, allowing translation from older
formats that have different sizes for the structures in ctf.h:
currently, these older formats are intermingled with the newer ones in
ctf.h: they will probably migrate to a compatibility header in time, to
ease readability.  The ctf_set_base() function is split out for the same
reason: when conversion code to a newer format is written, it would need
to malloc() new storage for the entire ctf_file_t if a file format
change causes it to grow, and for that we need ctf_set_base() to be a
separate function.

One pair of linked data structures supported by this file has no
creation code in libctf yet: the data and function object sections read
by init_symtab(). These will probably arrive soon, when the linker comes
to need them. (init_symtab() has hardly been changed since 2009, but if
any code in libctf has rotted over time, this will.)

A few simple accessors are also present that can even be called on
read-only containers because they don't actually modify them, since the
relevant things are not stored in the container but merely change its
operation: ctf_setmodel(), which lets you specify whether a container is
LP64 or not (used to statically determine the sizes of a few types),
ctf_import(), which is the only way to associate a parent container with
a child container, and ctf_setspecific(), which lets the caller
associate an arbitrary pointer with the CTF container for any use. If
the user doesn't call these functions correctly, libctf will misbehave:
this is particularly important for ctf_import(), since a container built
against a given parent container will not be able to resolve types that
depend on types in the parent unless it is ctf_import()ed with a parent
container with the same set of types at the same IDs, or a superset.

Possible future extensions (also noted in the ctf-hash.c file) include
storing a count of things so that we don't need to do one pass over the
CTF file counting everything, and computing a perfect hash at CTF
creation time in some compact form, storing it in the CTF file, and
using it to hash things so we don't need to do a second pass over the
entire CTF file to set up the hashes used to go from names to type IDs.
(There are multiple such hashes, one for each C type namespace: types,
enums, structs, and unions.)

Changes from v1:
 - Correct erroneous license (GPLv2+ -> v3+) and reset copyright years.
 - Introduce compatibility loading code for format v1 (mostly because
   the next posting of this patch series will change it to handle
   v1+v2->v3 when we introduce v3).
 - Drop Linux-specific <byteswap.h> and <elf.h> in favour of
   libctf-internal equivalents which are hopefully more portable;
   we also use <bfd.h> and "elf-bfd.h", but this is only for the
   sake of the SHN_* constants: no bfd functions are called from
   ctf-open.c, so readelf can use it without pulling in bfd.
 - Drop LCTF_MMAP (no longer supportable with bfd).
 - Add support for freeing ctf, symtab and strtab data that was
   allocated by the library (acquired from bfd), and for munmapping
   mmapped ctf data (acquired from a CTF archive); add an internal
   hook, fp->ctf_bfd_close, to ask BFD to close the file too
 - No longer use mmap constants; use libctf_init_debug(); adjust
   to ctf_free() prototype change

libctf/
	* ctf-open.c: New file.
	* swap.h: Likewise.
include/
	* ctf-api.h (ctf_close): New declaration.
	(ctf_getdatasect): Likewise.
	(ctf_parent_file): Likewise.
	(ctf_parent_name): Likewise.
	(ctf_parent_name_set): Likewise.
	(ctf_import): Likewise.
	(ctf_setmodel): Likewise.
	(ctf_getmodel): Likewise.
	(ctf_setspecific): Likewise.
	(ctf_getspecific): Likewise.
---
 include/ctf-api.h |   13 +
 libctf/ctf-open.c | 1687 +++++++++++++++++++++++++++++++++++++++++++++
 libctf/swap.h     |   60 ++
 3 files changed, 1760 insertions(+)
 create mode 100644 libctf/ctf-open.c
 create mode 100644 libctf/swap.h

diff --git a/include/ctf-api.h b/include/ctf-api.h
index 030770649e..c5eb9c676b 100644
--- a/include/ctf-api.h
+++ b/include/ctf-api.h
@@ -203,6 +203,19 @@ extern ctf_file_t *ctf_simple_open (const char *, size_t, const char *, size_t,
 extern ctf_file_t *ctf_bufopen (const ctf_sect_t *, const ctf_sect_t *,
 				const ctf_sect_t *, int *);
 extern ctf_file_t *ctf_create (int *);
+extern void ctf_close (ctf_file_t *);
+extern ctf_sect_t ctf_getdatasect (const ctf_file_t *);
+
+extern ctf_file_t *ctf_parent_file (ctf_file_t *);
+extern const char *ctf_parent_name (ctf_file_t *);
+extern void ctf_parent_name_set (ctf_file_t *, const char *);
+
+extern int ctf_import (ctf_file_t *, ctf_file_t *);
+extern int ctf_setmodel (ctf_file_t *, int);
+extern int ctf_getmodel (ctf_file_t *);
+
+extern void ctf_setspecific (ctf_file_t *, void *);
+extern void *ctf_getspecific (ctf_file_t *);
 
 extern int ctf_errno (ctf_file_t *);
 extern const char *ctf_errmsg (int);
diff --git a/libctf/ctf-open.c b/libctf/ctf-open.c
new file mode 100644
index 0000000000..ca256001b7
--- /dev/null
+++ b/libctf/ctf-open.c
@@ -0,0 +1,1687 @@
+/* Opening CTF files.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+
+   This file is part of libctf.
+
+   libctf is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+   See the GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <ctf-impl.h>
+#include <stddef.h>
+#include <string.h>
+#include <sys/types.h>
+#include <elf.h>
+#include <assert.h>
+#include "swap.h"
+#include <bfd.h>
+#include <zlib.h>
+
+#include "elf-bfd.h"
+
+static const ctf_dmodel_t _libctf_models[] = {
+  {"ILP32", CTF_MODEL_ILP32, 4, 1, 2, 4, 4},
+  {"LP64", CTF_MODEL_LP64, 8, 1, 2, 4, 8},
+  {NULL, 0, 0, 0, 0, 0, 0}
+};
+
+const char _CTF_SECTION[] = ".ctf";
+const char _CTF_NULLSTR[] = "";
+
+/* Version-sensitive accessors.  */
+
+static uint32_t
+get_kind_v1 (uint32_t info)
+{
+  return (CTF_V1_INFO_KIND (info));
+}
+
+static uint32_t
+get_root_v1 (uint32_t info)
+{
+  return (CTF_V1_INFO_ISROOT (info));
+}
+
+static uint32_t
+get_vlen_v1 (uint32_t info)
+{
+  return (CTF_V1_INFO_VLEN (info));
+}
+
+static uint32_t
+get_kind_v2 (uint32_t info)
+{
+  return (CTF_V2_INFO_KIND (info));
+}
+
+static uint32_t
+get_root_v2 (uint32_t info)
+{
+  return (CTF_V2_INFO_ISROOT (info));
+}
+
+static uint32_t
+get_vlen_v2 (uint32_t info)
+{
+  return (CTF_V2_INFO_VLEN (info));
+}
+
+static inline ssize_t
+get_ctt_size_common (const ctf_file_t *fp _libctf_unused_,
+		     const ctf_type_t *tp _libctf_unused_,
+		     ssize_t *sizep, ssize_t *incrementp, size_t lsize,
+		     size_t csize, size_t ctf_type_size,
+		     size_t ctf_stype_size, size_t ctf_lsize_sent)
+{
+  ssize_t size, increment;
+
+  if (csize == ctf_lsize_sent)
+    {
+      size = lsize;
+      increment = ctf_type_size;
+    }
+  else
+    {
+      size = csize;
+      increment = ctf_stype_size;
+    }
+
+  if (sizep)
+    *sizep = size;
+  if (incrementp)
+    *incrementp = increment;
+
+  return size;
+}
+
+static ssize_t
+get_ctt_size_v1 (const ctf_file_t *fp, const ctf_type_t *tp,
+		 ssize_t *sizep, ssize_t *incrementp)
+{
+  ctf_type_v1_t *t1p = (ctf_type_v1_t *) tp;
+
+  return (get_ctt_size_common (fp, tp, sizep, incrementp,
+			       CTF_TYPE_LSIZE (t1p), t1p->ctt_size,
+			       sizeof (ctf_type_v1_t), sizeof (ctf_stype_v1_t),
+			       CTF_LSIZE_SENT_V1));
+}
+
+/* Return the size that a v1 will be once it is converted to v2.  */
+
+static ssize_t
+get_ctt_size_v2_unconverted (const ctf_file_t *fp, const ctf_type_t *tp,
+			     ssize_t *sizep, ssize_t *incrementp)
+{
+  ctf_type_v1_t *t1p = (ctf_type_v1_t *) tp;
+
+  return (get_ctt_size_common (fp, tp, sizep, incrementp,
+			       CTF_TYPE_LSIZE (t1p), t1p->ctt_size,
+			       sizeof (ctf_type_t), sizeof (ctf_stype_t),
+			       CTF_LSIZE_SENT));
+}
+
+static ssize_t
+get_ctt_size_v2 (const ctf_file_t *fp, const ctf_type_t *tp,
+		 ssize_t *sizep, ssize_t *incrementp)
+{
+  return (get_ctt_size_common (fp, tp, sizep, incrementp,
+			       CTF_TYPE_LSIZE (tp), tp->ctt_size,
+			       sizeof (ctf_type_t), sizeof (ctf_stype_t),
+			       CTF_LSIZE_SENT));
+}
+
+static ssize_t
+get_vbytes_common (unsigned short kind, ssize_t size _libctf_unused_,
+		   size_t vlen)
+{
+  switch (kind)
+    {
+    case CTF_K_INTEGER:
+    case CTF_K_FLOAT:
+      return (sizeof (uint32_t));
+    case CTF_K_SLICE:
+      return (offsetof (ctf_slice_t, cts_bits) +
+	      sizeof (((ctf_slice_t *)0)->cts_bits));
+    case CTF_K_ENUM:
+      return (sizeof (ctf_enum_t) * vlen);
+    case CTF_K_FORWARD:
+    case CTF_K_UNKNOWN:
+    case CTF_K_POINTER:
+    case CTF_K_TYPEDEF:
+    case CTF_K_VOLATILE:
+    case CTF_K_CONST:
+    case CTF_K_RESTRICT:
+      return 0;
+    default:
+      ctf_dprintf ("detected invalid CTF kind -- %x\n", kind);
+      return ECTF_CORRUPT;
+    }
+}
+
+static ssize_t
+get_vbytes_v1 (unsigned short kind, ssize_t size, size_t vlen)
+{
+  switch (kind)
+    {
+    case CTF_K_ARRAY:
+      return (sizeof (ctf_array_v1_t));
+    case CTF_K_FUNCTION:
+      return (sizeof (unsigned short) * (vlen + (vlen & 1)));
+    case CTF_K_STRUCT:
+    case CTF_K_UNION:
+      if (size < CTF_LSTRUCT_THRESH_V1)
+	return (sizeof (ctf_member_v1_t) * vlen);
+      else
+	return (sizeof (ctf_lmember_v1_t) * vlen);
+    }
+
+  return (get_vbytes_common (kind, size, vlen));
+}
+
+static ssize_t
+get_vbytes_v2 (unsigned short kind, ssize_t size, size_t vlen)
+{
+  switch (kind)
+    {
+    case CTF_K_ARRAY:
+      return (sizeof (ctf_array_t));
+    case CTF_K_FUNCTION:
+      return (sizeof (uint32_t) * (vlen + (vlen & 1)));
+    case CTF_K_STRUCT:
+    case CTF_K_UNION:
+      if (size < CTF_LSTRUCT_THRESH)
+	return (sizeof (ctf_member_t) * vlen);
+      else
+	return (sizeof (ctf_lmember_t) * vlen);
+    }
+
+  return (get_vbytes_common (kind, size, vlen));
+}
+
+static const ctf_fileops_t ctf_fileops[] = {
+  {NULL, NULL, NULL, NULL, NULL},
+  /* CTF_VERSION_1 */
+  {get_kind_v1, get_root_v1, get_vlen_v1, get_ctt_size_v1, get_vbytes_v1},
+  /* CTF_VERSION_1_UPGRADED_3 */
+  {get_kind_v2, get_root_v2, get_vlen_v2, get_ctt_size_v2, get_vbytes_v2},
+  /* CTF_VERSION_2 */
+  {get_kind_v2, get_root_v2, get_vlen_v2, get_ctt_size_v2, get_vbytes_v2},
+  /* CTF_VERSION_3, identical to 2: only new type kinds */
+  {get_kind_v2, get_root_v2, get_vlen_v2, get_ctt_size_v2, get_vbytes_v2},
+};
+
+/* Initialize the symtab translation table by filling each entry with the
+  offset of the CTF type or function data corresponding to each STT_FUNC or
+  STT_OBJECT entry in the symbol table.  */
+
+static int
+init_symtab (ctf_file_t *fp, const ctf_header_t *hp,
+	     const ctf_sect_t *sp, const ctf_sect_t *strp)
+{
+  const unsigned char *symp = sp->cts_data;
+  uint32_t *xp = fp->ctf_sxlate;
+  uint32_t *xend = xp + fp->ctf_nsyms;
+
+  uint32_t objtoff = hp->cth_objtoff;
+  uint32_t funcoff = hp->cth_funcoff;
+
+  uint32_t info, vlen;
+  Elf64_Sym sym, *gsp;
+  const char *name;
+
+  /* The CTF data object and function type sections are ordered to match
+     the relative order of the respective symbol types in the symtab.
+     If no type information is available for a symbol table entry, a
+     pad is inserted in the CTF section.  As a further optimization,
+     anonymous or undefined symbols are omitted from the CTF data.  */
+
+  for (; xp < xend; xp++, symp += sp->cts_entsize)
+    {
+      if (sp->cts_entsize == sizeof (Elf32_Sym))
+	gsp = ctf_sym_to_elf64 ((Elf32_Sym *) (uintptr_t) symp, &sym);
+      else
+	gsp = (Elf64_Sym *) (uintptr_t) symp;
+
+      if (gsp->st_name < strp->cts_size)
+	name = (const char *) strp->cts_data + gsp->st_name;
+      else
+	name = _CTF_NULLSTR;
+
+      if (gsp->st_name == 0 || gsp->st_shndx == SHN_UNDEF
+	  || strcmp (name, "_START_") == 0 || strcmp (name, "_END_") == 0)
+	{
+	  *xp = -1u;
+	  continue;
+	}
+
+      switch (ELF64_ST_TYPE (gsp->st_info))
+	{
+	case STT_OBJECT:
+	  if (objtoff >= hp->cth_funcoff
+	      || (gsp->st_shndx == SHN_EXTABS && gsp->st_value == 0))
+	    {
+	      *xp = -1u;
+	      break;
+	    }
+
+	  *xp = objtoff;
+	  objtoff += sizeof (uint32_t);
+	  break;
+
+	case STT_FUNC:
+	  if (funcoff >= hp->cth_typeoff)
+	    {
+	      *xp = -1u;
+	      break;
+	    }
+
+	  *xp = funcoff;
+
+	  info = *(uint32_t *) ((uintptr_t) fp->ctf_buf + funcoff);
+	  vlen = LCTF_INFO_VLEN (fp, info);
+
+	  /* If we encounter a zero pad at the end, just skip it.  Otherwise
+	     skip over the function and its return type (+2) and the argument
+	     list (vlen).
+	   */
+	  if (LCTF_INFO_KIND (fp, info) == CTF_K_UNKNOWN && vlen == 0)
+	    funcoff += sizeof (uint32_t);	/* Skip pad.  */
+	  else
+	    funcoff += sizeof (uint32_t) * (vlen + 2);
+	  break;
+
+	default:
+	  *xp = -1u;
+	  break;
+	}
+    }
+
+  ctf_dprintf ("loaded %lu symtab entries\n", fp->ctf_nsyms);
+  return 0;
+}
+
+/* Set the CTF base pointer and derive the buf pointer from it, initializing
+   everything in the ctf_file that depends on the base or buf pointers.  */
+
+static void
+ctf_set_base (ctf_file_t *fp, const ctf_header_t *hp, void *base)
+{
+  fp->ctf_base = base;
+  fp->ctf_buf = fp->ctf_base + sizeof (ctf_header_t);
+  fp->ctf_vars = (ctf_varent_t *) ((const char *) fp->ctf_buf +
+				   hp->cth_varoff);
+  fp->ctf_nvars = (hp->cth_typeoff - hp->cth_varoff) / sizeof (ctf_varent_t);
+
+  fp->ctf_str[CTF_STRTAB_0].cts_strs = (const char *) fp->ctf_buf
+    + hp->cth_stroff;
+  fp->ctf_str[CTF_STRTAB_0].cts_len = hp->cth_strlen;
+
+  /* If we have a parent container name and label, store the relocated
+     string pointers in the CTF container for easy access later. */
+
+  /* Note: before conversion, these will be set to values that will be
+     immediately invalidated by the conversion process, but the conversion
+     process will call ctf_set_base() again to fix things up.  */
+
+  if (hp->cth_parlabel != 0)
+    fp->ctf_parlabel = ctf_strptr (fp, hp->cth_parlabel);
+  if (hp->cth_parname != 0)
+    fp->ctf_parname = ctf_strptr (fp, hp->cth_parname);
+
+  ctf_dprintf ("ctf_set_base: parent name %s (label %s)\n",
+	       fp->ctf_parname ? fp->ctf_parname : "<NULL>",
+	       fp->ctf_parlabel ? fp->ctf_parlabel : "<NULL>");
+}
+
+/* Free a ctf_base pointer: the pointer passed, or (if NULL) fp->ctf_base.  */
+static void
+ctf_free_base (ctf_file_t *fp, unsigned char *ctf_base, size_t ctf_size)
+{
+  unsigned char *base;
+  size_t size;
+
+  if (ctf_base)
+    {
+      base = ctf_base;
+      size = ctf_size;
+    }
+  else
+    {
+      base = (unsigned char *) fp->ctf_base;
+      size = fp->ctf_size;
+    }
+
+  if (base != fp->ctf_data.cts_data && base != NULL)
+    ctf_data_free (base, size);
+}
+
+/* Set the version of the CTF file. */
+
+/* When this is reset, LCTF_* changes behaviour, but there is no guarantee that
+   the variable data list associated with each type has been upgraded: the
+   caller must ensure this has been done in advance.  */
+
+static void
+ctf_set_version (ctf_file_t * fp, ctf_header_t * cth, int ctf_version)
+{
+  fp->ctf_version = ctf_version;
+  cth->cth_version = ctf_version;
+  fp->ctf_fileops = &ctf_fileops[ctf_version];
+}
+
+/* Upgrade the type table to CTF_VERSION_3 (really CTF_VERSION_1_UPGRADED_3).
+
+   The upgrade is not done in-place: the ctf_base is moved.  ctf_strptr() must
+   not be called before reallocation is complete.
+
+   Type kinds not checked here due to nonexistence in older formats:
+      CTF_K_SLICE.  */
+static int
+upgrade_types (ctf_file_t *fp, ctf_header_t *cth)
+{
+  const ctf_type_v1_t *tbuf;
+  const ctf_type_v1_t *tend;
+  unsigned char *ctf_base, *old_ctf_base = (unsigned char *) fp->ctf_base;
+  size_t old_ctf_size = fp->ctf_size;
+  ctf_type_t *t2buf;
+
+  ssize_t increase = 0, size, increment, v2increment, vbytes, v2bytes;
+  const ctf_type_v1_t *tp;
+  ctf_type_t *t2p;
+  ctf_header_t *new_cth;
+
+  tbuf = (ctf_type_v1_t *) (fp->ctf_buf + cth->cth_typeoff);
+  tend = (ctf_type_v1_t *) (fp->ctf_buf + cth->cth_stroff);
+
+  /* Much like init_types(), this is a two-pass process.
+
+     First, figure out the new type-section size needed.  (It is possible,
+     in theory, for it to be less than the old size, but this is very
+     unlikely.  It cannot be so small that cth_typeoff ends up of negative
+     size.  We validate this with an assertion below.)
+
+     We must cater not only for changes in vlen and types sizes but also
+     for changes in 'increment', which happen because v2 places some types
+     into ctf_stype_t where v1 would be forced to use the larger non-stype.  */
+
+  for (tp = tbuf; tp < tend;
+       tp = (ctf_type_v1_t *) ((uintptr_t) tp + increment + vbytes))
+    {
+      unsigned short kind = CTF_V1_INFO_KIND (tp->ctt_info);
+      unsigned long vlen = CTF_V1_INFO_VLEN (tp->ctt_info);
+
+      size = get_ctt_size_v1 (fp, (const ctf_type_t *) tp, NULL, &increment);
+      vbytes = get_vbytes_v1 (kind, size, vlen);
+
+      get_ctt_size_v2_unconverted (fp, (const ctf_type_t *) tp, NULL,
+				   &v2increment);
+      v2bytes = get_vbytes_v2 (kind, size, vlen);
+
+      if ((vbytes < 0) || (size < 0))
+	return ECTF_CORRUPT;
+
+      increase += v2increment - increment;	/* May be negative.  */
+      increase += v2bytes - vbytes;
+    }
+
+  /* Allocate enough room for the new buffer, then copy everything but the
+     type section into place, and reset the base accordingly.  Leave the
+     version number unchanged, so that LCTF_INFO_* still works on the
+     as-yet-untranslated type info.  */
+
+  if ((ctf_base = ctf_data_alloc (fp->ctf_size + increase)) == NULL)
+    return ECTF_ZALLOC;
+
+  memcpy (ctf_base, fp->ctf_base, sizeof (ctf_header_t) + cth->cth_typeoff);
+  memcpy (ctf_base + sizeof (ctf_header_t) + cth->cth_stroff + increase,
+	  fp->ctf_base + sizeof (ctf_header_t) + cth->cth_stroff,
+	  cth->cth_strlen);
+
+  memset (ctf_base + sizeof (ctf_header_t) + cth->cth_typeoff, 0,
+	 cth->cth_stroff - cth->cth_typeoff + increase);
+
+  /* The cth here is an automatic variable in ctf_bufopen(), and transient
+     (a copy maintained because at that stage the header read out of the
+     ctf file may be read-only). We make all modifications in the
+     canonical copy at ctf_base (by now, writable), then copy it back into
+     cth at the end.  */
+
+  new_cth = (ctf_header_t *) ctf_base;
+  new_cth->cth_stroff += increase;
+  fp->ctf_size += increase;
+  assert (new_cth->cth_stroff >= new_cth->cth_typeoff);
+  ctf_set_base (fp, new_cth, ctf_base);
+
+  t2buf = (ctf_type_t *) (fp->ctf_buf + new_cth->cth_typeoff);
+
+  /* Iterate through all the types again, upgrading them.
+
+     Everything that hasn't changed can just be outright memcpy()ed.
+     Things that have changed need field-by-field consideration.  */
+
+  for (tp = tbuf, t2p = t2buf; tp < tend;
+       tp = (ctf_type_v1_t *) ((uintptr_t) tp + increment + vbytes),
+       t2p = (ctf_type_t *) ((uintptr_t) t2p + v2increment + v2bytes))
+    {
+      unsigned short kind = CTF_V1_INFO_KIND (tp->ctt_info);
+      int isroot = CTF_V1_INFO_ISROOT (tp->ctt_info);
+      unsigned long vlen = CTF_V1_INFO_VLEN (tp->ctt_info);
+      ssize_t v2size;
+      void *vdata, *v2data;
+
+      size = get_ctt_size_v1 (fp, (const ctf_type_t *) tp, NULL, &increment);
+      vbytes = get_vbytes_v1 (kind, size, vlen);
+
+      t2p->ctt_name = tp->ctt_name;
+      t2p->ctt_info = CTF_TYPE_INFO (kind, isroot, vlen);
+
+      switch (kind)
+	{
+	case CTF_K_FUNCTION:
+	case CTF_K_FORWARD:
+	case CTF_K_TYPEDEF:
+	case CTF_K_POINTER:
+	case CTF_K_VOLATILE:
+	case CTF_K_CONST:
+	case CTF_K_RESTRICT:
+	  t2p->ctt_type = tp->ctt_type;
+	  break;
+	case CTF_K_INTEGER:
+	case CTF_K_FLOAT:
+	case CTF_K_ARRAY:
+	case CTF_K_STRUCT:
+	case CTF_K_UNION:
+	case CTF_K_ENUM:
+	case CTF_K_UNKNOWN:
+	  if (size <= CTF_MAX_SIZE)
+	    t2p->ctt_size = size;
+	  else
+	    {
+	      t2p->ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (size);
+	      t2p->ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO (size);
+	    }
+	  break;
+	}
+
+      v2size = get_ctt_size_v2 (fp, t2p, NULL, &v2increment);
+      v2bytes = get_vbytes_v2 (kind, v2size, vlen);
+
+      /* Catch out-of-sync get_ctt_size_*().  The count goes wrong if
+	 these are not identical (and having them different makes no
+	 sense semantically).  */
+
+      assert (size == v2size);
+
+      /* Now the varlen info.  */
+
+      vdata = (void *) ((uintptr_t) tp + increment);
+      v2data = (void *) ((uintptr_t) t2p + v2increment);
+
+      switch (kind)
+	{
+	case CTF_K_ARRAY:
+	  {
+	    const ctf_array_v1_t *ap = (const ctf_array_v1_t *) vdata;
+	    ctf_array_t *a2p = (ctf_array_t *) v2data;
+
+	    a2p->cta_contents = ap->cta_contents;
+	    a2p->cta_index = ap->cta_index;
+	    a2p->cta_nelems = ap->cta_nelems;
+	    break;
+	  }
+	case CTF_K_STRUCT:
+	case CTF_K_UNION:
+	  {
+	    ctf_member_t tmp;
+	    const ctf_member_v1_t *m1 = (const ctf_member_v1_t *) vdata;
+	    const ctf_lmember_v1_t *lm1 = (const ctf_lmember_v1_t *) m1;
+	    ctf_member_t *m2 = (ctf_member_t *) v2data;
+	    ctf_lmember_t *lm2 = (ctf_lmember_t *) m2;
+	    unsigned long i;
+
+	    /* We walk all four pointers forward, but only reference the two
+	       that are valid for the given size, to avoid quadruplicating all
+	       the code.  */
+
+	    for (i = vlen; i != 0; i--, m1++, lm1++, m2++, lm2++)
+	      {
+		size_t offset;
+		if (size < CTF_LSTRUCT_THRESH_V1)
+		  {
+		    offset = m1->ctm_offset;
+		    tmp.ctm_name = m1->ctm_name;
+		    tmp.ctm_type = m1->ctm_type;
+		  }
+		else
+		  {
+		    offset = CTF_LMEM_OFFSET (lm1);
+		    tmp.ctm_name = lm1->ctlm_name;
+		    tmp.ctm_type = lm1->ctlm_type;
+		  }
+		if (size < CTF_LSTRUCT_THRESH)
+		  {
+		    m2->ctm_name = tmp.ctm_name;
+		    m2->ctm_type = tmp.ctm_type;
+		    m2->ctm_offset = offset;
+		  }
+		else
+		  {
+		    lm2->ctlm_name = tmp.ctm_name;
+		    lm2->ctlm_type = tmp.ctm_type;
+		    lm2->ctlm_offsethi = CTF_OFFSET_TO_LMEMHI (offset);
+		    lm2->ctlm_offsetlo = CTF_OFFSET_TO_LMEMLO (offset);
+		  }
+	      }
+	    break;
+	  }
+	case CTF_K_FUNCTION:
+	  {
+	    unsigned long i;
+	    unsigned short *a1 = (unsigned short *) vdata;
+	    uint32_t *a2 = (uint32_t *) v2data;
+
+	    for (i = vlen; i != 0; i--, a1++, a2++)
+	      *a2 = *a1;
+	  }
+	/* FALLTHRU */
+	default:
+	  /* Catch out-of-sync get_vbytes_*().  */
+	  assert (vbytes == v2bytes);
+	  memcpy (v2data, vdata, vbytes);
+	}
+    }
+
+  /* Verify that the entire region was converted.  If not, we are either
+     converting too much, or too little (leading to a buffer overrun either here
+     or at read time, in init_types().) */
+
+  assert ((size_t) t2p - (size_t) fp->ctf_buf == new_cth->cth_stroff);
+
+  ctf_set_version (fp, (ctf_header_t *) ctf_base, CTF_VERSION_1_UPGRADED_3);
+  ctf_free_base (fp, old_ctf_base, old_ctf_size);
+  memcpy (cth, new_cth, sizeof (ctf_header_t));
+
+  return 0;
+}
+
+/* Initialize the type ID translation table with the byte offset of each type,
+   and initialize the hash tables of each named type.  Upgrade the type table to
+   the latest supported representation in the process, if needed, and if this
+   recension of libctf supports upgrading.  */
+
+static int
+init_types (ctf_file_t *fp, ctf_header_t *cth)
+{
+  const ctf_type_t *tbuf;
+  const ctf_type_t *tend;
+
+  unsigned long pop[CTF_K_MAX + 1] = { 0 };
+  const ctf_type_t *tp;
+  ctf_hash_t *hp;
+  uint32_t id, dst;
+  uint32_t *xp;
+
+  /* We determine whether the container is a child or a parent based on
+     the value of cth_parname.  */
+
+  int child = cth->cth_parname != 0;
+  int nlstructs = 0, nlunions = 0;
+  int err;
+
+  if (_libctf_unlikely_ (fp->ctf_version == CTF_VERSION_1))
+    {
+      int err;
+      if ((err = upgrade_types (fp, cth)) != 0)
+	return err;				/* Upgrade failed.  */
+    }
+
+  tbuf = (ctf_type_t *) (fp->ctf_buf + cth->cth_typeoff);
+  tend = (ctf_type_t *) (fp->ctf_buf + cth->cth_stroff);
+
+  /* We make two passes through the entire type section.  In this first
+     pass, we count the number of each type and the total number of types.  */
+
+  for (tp = tbuf; tp < tend; fp->ctf_typemax++)
+    {
+      unsigned short kind = LCTF_INFO_KIND (fp, tp->ctt_info);
+      unsigned long vlen = LCTF_INFO_VLEN (fp, tp->ctt_info);
+      ssize_t size, increment, vbytes;
+
+      (void) ctf_get_ctt_size (fp, tp, &size, &increment);
+      vbytes = LCTF_VBYTES (fp, kind, size, vlen);
+
+      if (vbytes < 0)
+	return ECTF_CORRUPT;
+
+      if (kind == CTF_K_FORWARD)
+	{
+	  /* For forward declarations, ctt_type is the CTF_K_* kind for the tag,
+	     so bump that population count too.  If ctt_type is unknown, treat
+	     the tag as a struct.  */
+
+	  if (tp->ctt_type == CTF_K_UNKNOWN || tp->ctt_type >= CTF_K_MAX)
+	    pop[CTF_K_STRUCT]++;
+	  else
+	    pop[tp->ctt_type]++;
+	}
+      tp = (ctf_type_t *) ((uintptr_t) tp + increment + vbytes);
+      pop[kind]++;
+    }
+
+  if (child)
+    {
+      ctf_dprintf ("CTF container %p is a child\n", (void *) fp);
+      fp->ctf_flags |= LCTF_CHILD;
+    }
+  else
+    ctf_dprintf ("CTF container %p is a parent\n", (void *) fp);
+
+  /* Now that we've counted up the number of each type, we can allocate
+     the hash tables, type translation table, and pointer table.  */
+
+  if ((fp->ctf_structs = ctf_hash_create (pop[CTF_K_STRUCT], ctf_hash_string,
+					  ctf_hash_eq_string)) == NULL)
+    return ENOMEM;
+
+  if ((fp->ctf_unions = ctf_hash_create (pop[CTF_K_UNION], ctf_hash_string,
+					 ctf_hash_eq_string)) == NULL)
+    return ENOMEM;
+
+  if ((fp->ctf_enums = ctf_hash_create (pop[CTF_K_ENUM], ctf_hash_string,
+					ctf_hash_eq_string)) == NULL)
+    return ENOMEM;
+
+  if ((fp->ctf_names = ctf_hash_create (pop[CTF_K_INTEGER] +
+					pop[CTF_K_FLOAT] +
+					pop[CTF_K_FUNCTION] +
+					pop[CTF_K_TYPEDEF] +
+					pop[CTF_K_POINTER] +
+					pop[CTF_K_VOLATILE] +
+					pop[CTF_K_CONST] +
+					pop[CTF_K_RESTRICT],
+					ctf_hash_string,
+					ctf_hash_eq_string)) == NULL)
+    return ENOMEM;
+
+  fp->ctf_txlate = ctf_alloc (sizeof (uint32_t) * (fp->ctf_typemax + 1));
+  fp->ctf_ptrtab = ctf_alloc (sizeof (uint32_t) * (fp->ctf_typemax + 1));
+
+  if (fp->ctf_txlate == NULL || fp->ctf_ptrtab == NULL)
+    return ENOMEM;		/* Memory allocation failed.  */
+
+  xp = fp->ctf_txlate;
+  *xp++ = 0;			/* Type id 0 is used as a sentinel value.  */
+
+  memset (fp->ctf_txlate, 0, sizeof (uint32_t) * (fp->ctf_typemax + 1));
+  memset (fp->ctf_ptrtab, 0, sizeof (uint32_t) * (fp->ctf_typemax + 1));
+
+  /* In the second pass through the types, we fill in each entry of the
+     type and pointer tables and add names to the appropriate hashes.  */
+
+  for (id = 1, tp = tbuf; tp < tend; xp++, id++)
+    {
+      unsigned short kind = LCTF_INFO_KIND (fp, tp->ctt_info);
+      unsigned short flag = LCTF_INFO_ISROOT (fp, tp->ctt_info);
+      unsigned long vlen = LCTF_INFO_VLEN (fp, tp->ctt_info);
+      ssize_t size, increment, vbytes;
+
+      const char *name;
+
+      (void) ctf_get_ctt_size (fp, tp, &size, &increment);
+      name = ctf_strptr (fp, tp->ctt_name);
+      vbytes = LCTF_VBYTES (fp, kind, size, vlen);
+
+      switch (kind)
+	{
+	case CTF_K_INTEGER:
+	case CTF_K_FLOAT:
+	  /* Names are reused by bit-fields, which are differentiated by their
+	     encodings, and so typically we'd record only the first instance of
+	     a given intrinsic.  However, we replace an existing type with a
+	     root-visible version so that we can be sure to find it when
+	     checking for conflicting definitions in ctf_add_type().  */
+
+	  if (((ctf_hash_lookup_type (fp->ctf_names, fp, name)) == 0)
+	      || (flag & CTF_ADD_ROOT))
+	    {
+	      err = ctf_hash_define_type (fp->ctf_names, fp,
+					  LCTF_INDEX_TO_TYPE (fp, id, child),
+					  tp->ctt_name);
+	      if (err != 0 && err != ECTF_STRTAB)
+		return err;
+	    }
+	  break;
+
+	  /* These kinds have no name, so do not need interning into any
+	     hashtables.  */
+	case CTF_K_ARRAY:
+	case CTF_K_SLICE:
+	  break;
+
+	case CTF_K_FUNCTION:
+	  err = ctf_hash_insert_type (fp->ctf_names, fp,
+				      LCTF_INDEX_TO_TYPE (fp, id, child),
+				      tp->ctt_name);
+	  if (err != 0 && err != ECTF_STRTAB)
+	    return err;
+	  break;
+
+	case CTF_K_STRUCT:
+	  err = ctf_hash_define_type (fp->ctf_structs, fp,
+				      LCTF_INDEX_TO_TYPE (fp, id, child),
+				      tp->ctt_name);
+
+	  if (err != 0 && err != ECTF_STRTAB)
+	    return err;
+
+	  if (size >= CTF_LSTRUCT_THRESH)
+	    nlstructs++;
+	  break;
+
+	case CTF_K_UNION:
+	  err = ctf_hash_define_type (fp->ctf_unions, fp,
+				      LCTF_INDEX_TO_TYPE (fp, id, child),
+				      tp->ctt_name);
+
+	  if (err != 0 && err != ECTF_STRTAB)
+	    return err;
+
+	  if (size >= CTF_LSTRUCT_THRESH)
+	    nlunions++;
+	  break;
+
+	case CTF_K_ENUM:
+	  err = ctf_hash_define_type (fp->ctf_enums, fp,
+				      LCTF_INDEX_TO_TYPE (fp, id, child),
+				      tp->ctt_name);
+
+	  if (err != 0 && err != ECTF_STRTAB)
+	    return err;
+	  break;
+
+	case CTF_K_TYPEDEF:
+	  err = ctf_hash_insert_type (fp->ctf_names, fp,
+				      LCTF_INDEX_TO_TYPE (fp, id, child),
+				      tp->ctt_name);
+	  if (err != 0 && err != ECTF_STRTAB)
+	    return err;
+	  break;
+
+	case CTF_K_FORWARD:
+	  /* Only insert forward tags into the given hash if the type or tag
+	     name is not already present.  */
+	  switch (tp->ctt_type)
+	    {
+	    case CTF_K_STRUCT:
+	      hp = fp->ctf_structs;
+	      break;
+	    case CTF_K_UNION:
+	      hp = fp->ctf_unions;
+	      break;
+	    case CTF_K_ENUM:
+	      hp = fp->ctf_enums;
+	      break;
+	    default:
+	      hp = fp->ctf_structs;
+	    }
+
+	  if (ctf_hash_lookup_type (hp, fp, name) == 0)
+	    {
+	      err = ctf_hash_insert_type (hp, fp,
+					  LCTF_INDEX_TO_TYPE (fp, id, child),
+					  tp->ctt_name);
+	      if (err != 0 && err != ECTF_STRTAB)
+		return err;
+	    }
+	  break;
+
+	case CTF_K_POINTER:
+	  /* If the type referenced by the pointer is in this CTF container,
+	     then store the index of the pointer type in
+	     fp->ctf_ptrtab[ index of referenced type ].  */
+
+	  if (LCTF_TYPE_ISCHILD (fp, tp->ctt_type) == child
+	      && LCTF_TYPE_TO_INDEX (fp, tp->ctt_type) <= fp->ctf_typemax)
+	    fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX (fp, tp->ctt_type)] = id;
+	 /*FALLTHRU*/
+
+	case CTF_K_VOLATILE:
+	case CTF_K_CONST:
+	case CTF_K_RESTRICT:
+	  err = ctf_hash_insert_type (fp->ctf_names, fp,
+				      LCTF_INDEX_TO_TYPE (fp, id, child),
+				      tp->ctt_name);
+	  if (err != 0 && err != ECTF_STRTAB)
+	    return err;
+	  break;
+	}
+
+      *xp = (uint32_t) ((uintptr_t) tp - (uintptr_t) fp->ctf_buf);
+      tp = (ctf_type_t *) ((uintptr_t) tp + increment + vbytes);
+    }
+
+  ctf_dprintf ("%lu total types processed\n", fp->ctf_typemax);
+  ctf_dprintf ("%u enum names hashed\n", ctf_hash_size (fp->ctf_enums));
+  ctf_dprintf ("%u struct names hashed (%d long)\n",
+	       ctf_hash_size (fp->ctf_structs), nlstructs);
+  ctf_dprintf ("%u union names hashed (%d long)\n",
+	       ctf_hash_size (fp->ctf_unions), nlunions);
+  ctf_dprintf ("%u base type names hashed\n", ctf_hash_size (fp->ctf_names));
+
+  /* Make an additional pass through the pointer table to find pointers that
+     point to anonymous typedef nodes.  If we find one, modify the pointer table
+     so that the pointer is also known to point to the node that is referenced
+     by the anonymous typedef node.  */
+
+  for (id = 1; id <= fp->ctf_typemax; id++)
+    {
+      if ((dst = fp->ctf_ptrtab[id]) != 0)
+	{
+	  tp = LCTF_INDEX_TO_TYPEPTR (fp, id);
+
+	  if (LCTF_INFO_KIND (fp, tp->ctt_info) == CTF_K_TYPEDEF &&
+	      strcmp (ctf_strptr (fp, tp->ctt_name), "") == 0 &&
+	      LCTF_TYPE_ISCHILD (fp, tp->ctt_type) == child &&
+	      LCTF_TYPE_TO_INDEX (fp, tp->ctt_type) <= fp->ctf_typemax)
+	    fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX (fp, tp->ctt_type)] = dst;
+	}
+    }
+
+  return 0;
+}
+
+/* Endianness-flipping routines.
+
+   We flip everything, mindlessly, even 1-byte entities, so that future
+   expansions do not require changes to this code.  */
+
+/* < C11? define away static assertions.  */
+
+#if !defined (__STDC_VERSION__) || __STDC_VERSION__ < 201112L
+#define _Static_assert(cond, err)
+#endif
+
+/* Swap the endianness of something.  */
+
+#define swap_thing(x)							\
+  do {									\
+    _Static_assert (sizeof (x) == 1 || (sizeof (x) % 2 == 0		\
+					&& sizeof (x) <= 8),		\
+		    "Invalid size, update endianness code");		\
+    switch (sizeof (x)) {						\
+    case 2: x = bswap_16 (x); break;					\
+    case 4: x = bswap_32 (x); break;					\
+    case 8: x = bswap_64 (x); break;					\
+    case 1: /* Nothing needs doing */					\
+      break;								\
+    }									\
+  } while (0);
+
+/* Flip the endianness of the CTF header.  */
+
+static void
+flip_header (ctf_header_t *cth)
+{
+  swap_thing (cth->cth_preamble.ctp_magic);
+  swap_thing (cth->cth_preamble.ctp_version);
+  swap_thing (cth->cth_preamble.ctp_flags);
+  swap_thing (cth->cth_parlabel);
+  swap_thing (cth->cth_parname);
+  swap_thing (cth->cth_objtoff);
+  swap_thing (cth->cth_funcoff);
+  swap_thing (cth->cth_varoff);
+  swap_thing (cth->cth_typeoff);
+  swap_thing (cth->cth_stroff);
+  swap_thing (cth->cth_strlen);
+}
+
+/* Flip the endianness of the label section, an array of ctf_lblent_t.  */
+
+static void
+flip_lbls (void *start, size_t len)
+{
+  ctf_lblent_t *lbl = start;
+
+  for (ssize_t i = len / sizeof (struct ctf_lblent); i > 0; lbl++, i--)
+    {
+      swap_thing (lbl->ctl_label);
+      swap_thing (lbl->ctl_type);
+    }
+}
+
+/* Flip the endianness of the data-object or function sections, an array of
+   uint32_t.  (The function section has more internal structure, but that
+   structure is an array of uint32_t, so can be treated as one big array for
+   byte-swapping.)  */
+
+static void
+flip_objts (void *start, size_t len)
+{
+  uint32_t *obj = start;
+
+  for (ssize_t i = len / sizeof (uint32_t); i > 0; obj++, i--)
+      swap_thing (*obj);
+}
+
+/* Flip the endianness of the variable section, an array of ctf_varent_t.  */
+
+static void
+flip_vars (void *start, size_t len)
+{
+  ctf_varent_t *var = start;
+
+  for (ssize_t i = len / sizeof (struct ctf_varent); i > 0; var++, i--)
+    {
+      swap_thing (var->ctv_name);
+      swap_thing (var->ctv_type);
+    }
+}
+
+/* Flip the endianness of the type section, a tagged array of ctf_type or
+   ctf_stype followed by variable data.  */
+
+static int
+flip_types (void *start, size_t len)
+{
+  ctf_type_t *t = start;
+
+  while ((uintptr_t) t < ((uintptr_t) start) + len)
+    {
+      swap_thing (t->ctt_name);
+      swap_thing (t->ctt_info);
+      swap_thing (t->ctt_size);
+
+      uint32_t kind = CTF_V2_INFO_KIND (t->ctt_info);
+      size_t size = t->ctt_size;
+      uint32_t vlen = CTF_V2_INFO_VLEN (t->ctt_info);
+      size_t vbytes = get_vbytes_v2 (kind, size, vlen);
+
+      if (_libctf_unlikely_ (size == CTF_LSIZE_SENT))
+	{
+	  swap_thing (t->ctt_lsizehi);
+	  swap_thing (t->ctt_lsizelo);
+	  size = CTF_TYPE_LSIZE (t);
+	  t = (ctf_type_t *) ((uintptr_t) t + sizeof (ctf_type_t));
+	}
+      else
+	t = (ctf_type_t *) ((uintptr_t) t + sizeof (ctf_stype_t));
+
+      switch (kind)
+	{
+	case CTF_K_FORWARD:
+	case CTF_K_UNKNOWN:
+	case CTF_K_POINTER:
+	case CTF_K_TYPEDEF:
+	case CTF_K_VOLATILE:
+	case CTF_K_CONST:
+	case CTF_K_RESTRICT:
+	  /* These types have no vlen data to swap.  */
+	  assert (vbytes == 0);
+	  break;
+
+	case CTF_K_INTEGER:
+	case CTF_K_FLOAT:
+	  {
+	    /* These types have a single uint32_t.  */
+
+	    uint32_t *item = (uint32_t *) t;
+
+	    swap_thing (*item);
+	    break;
+	  }
+
+	case CTF_K_FUNCTION:
+	  {
+	    /* This type has a bunch of uint32_ts.  */
+
+	    uint32_t *item = (uint32_t *) t;
+
+	    for (ssize_t i = vlen; i > 0; item++, i--)
+	      swap_thing (*item);
+	    break;
+	  }
+
+	case CTF_K_ARRAY:
+	  {
+	    /* This has a single ctf_array_t.  */
+
+	    ctf_array_t *a = (ctf_array_t *) t;
+
+	    assert (vbytes == sizeof (ctf_array_t));
+	    swap_thing (a->cta_contents);
+	    swap_thing (a->cta_index);
+	    swap_thing (a->cta_nelems);
+
+	    break;
+	  }
+
+	case CTF_K_SLICE:
+	  {
+	    /* This has a single ctf_slice_t.  */
+
+	    ctf_slice_t *s = (ctf_slice_t *) t;
+
+	    assert (vbytes == sizeof (ctf_slice_t));
+	    swap_thing (s->cts_type);
+	    swap_thing (s->cts_offset);
+	    swap_thing (s->cts_bits);
+
+	    break;
+	  }
+
+	case CTF_K_STRUCT:
+	case CTF_K_UNION:
+	  {
+	    /* This has an array of ctf_member or ctf_lmember, depending on
+	       size.  We could consider it to be a simple array of uint32_t,
+	       but for safety's sake in case these structures ever acquire
+	       non-uint32_t members, do it member by member.  */
+
+	    if (_libctf_unlikely_ (size >= CTF_LSTRUCT_THRESH))
+	      {
+		ctf_lmember_t *lm = (ctf_lmember_t *) t;
+		for (ssize_t i = vlen; i > 0; i--, lm++)
+		  {
+		    swap_thing (lm->ctlm_name);
+		    swap_thing (lm->ctlm_offsethi);
+		    swap_thing (lm->ctlm_type);
+		    swap_thing (lm->ctlm_offsetlo);
+		  }
+	      }
+	    else
+	      {
+		ctf_member_t *m = (ctf_member_t *) t;
+		for (ssize_t i = vlen; i > 0; i--, m++)
+		  {
+		    swap_thing (m->ctm_name);
+		    swap_thing (m->ctm_offset);
+		    swap_thing (m->ctm_type);
+		  }
+	      }
+	    break;
+	  }
+
+	case CTF_K_ENUM:
+	  {
+	    /* This has an array of ctf_enum_t.  */
+
+	    ctf_enum_t *item = (ctf_enum_t *) t;
+
+	    for (ssize_t i = vlen; i > 0; item++, i--)
+	      {
+		swap_thing (item->cte_name);
+		swap_thing (item->cte_value);
+	      }
+	    break;
+	  }
+	default:
+	  ctf_dprintf ("unhandled CTF kind in endianness conversion -- %x\n",
+		       kind);
+	  return ECTF_CORRUPT;
+	}
+
+      t = (ctf_type_t *) ((uintptr_t) t + vbytes);
+    }
+
+  return 0;
+}
+
+/* Flip the endianness of BASE, given the offsets in the (already endian-
+   converted) CTH.
+
+   All of this stuff happens before the header is fully initialized, so the
+   LCTF_*() macros cannot be used yet.  Since we do not try to endian-convert v1
+   data, this is no real loss.  */
+
+static int
+flip_ctf (ctf_header_t *cth, unsigned char *base)
+{
+  base += sizeof (ctf_header_t);
+
+  flip_lbls (base + cth->cth_lbloff, cth->cth_objtoff - cth->cth_lbloff);
+  flip_objts (base + cth->cth_objtoff, cth->cth_funcoff - cth->cth_objtoff);
+  flip_objts (base + cth->cth_funcoff, cth->cth_varoff - cth->cth_funcoff);
+  flip_vars (base + cth->cth_varoff, cth->cth_typeoff - cth->cth_varoff);
+  return flip_types (base + cth->cth_typeoff, cth->cth_stroff - cth->cth_typeoff);
+}
+
+/* Open a CTF file, mocking up a suitable ctf_sect.  */
+ctf_file_t *ctf_simple_open (const char *ctfsect, size_t ctfsect_size,
+			     const char *symsect, size_t symsect_size,
+			     size_t symsect_entsize,
+			     const char *strsect, size_t strsect_size,
+			     int *errp)
+{
+  ctf_sect_t skeleton;
+
+  ctf_sect_t ctf_sect, sym_sect, str_sect;
+  ctf_sect_t *ctfsectp = NULL;
+  ctf_sect_t *symsectp = NULL;
+  ctf_sect_t *strsectp = NULL;
+
+  skeleton.cts_name = _CTF_SECTION;
+  skeleton.cts_type = SHT_PROGBITS;
+  skeleton.cts_flags = 0;
+  skeleton.cts_entsize = 1;
+  skeleton.cts_offset = 0;
+
+  if (ctfsect)
+    {
+      memcpy (&ctf_sect, &skeleton, sizeof (struct ctf_sect));
+      ctf_sect.cts_data = ctfsect;
+      ctf_sect.cts_size = ctfsect_size;
+      ctfsectp = &ctf_sect;
+    }
+
+  if (symsect)
+    {
+      memcpy (&sym_sect, &skeleton, sizeof (struct ctf_sect));
+      sym_sect.cts_data = symsect;
+      sym_sect.cts_size = symsect_size;
+      sym_sect.cts_entsize = symsect_entsize;
+      symsectp = &sym_sect;
+    }
+
+  if (strsect)
+    {
+      memcpy (&str_sect, &skeleton, sizeof (struct ctf_sect));
+      str_sect.cts_data = strsect;
+      str_sect.cts_size = strsect_size;
+      strsectp = &str_sect;
+    }
+
+  return ctf_bufopen (ctfsectp, symsectp, strsectp, errp);
+}
+
+/* Decode the specified CTF buffer and optional symbol table, and create a new
+   CTF container representing the symbolic debugging information.  This code can
+   be used directly by the debugger, or it can be used as the engine for
+   ctf_fdopen() or ctf_open(), below.  */
+
+ctf_file_t *
+ctf_bufopen (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
+	     const ctf_sect_t *strsect, int *errp)
+{
+  const ctf_preamble_t *pp;
+  ctf_header_t hp;
+  ctf_file_t *fp;
+  void *buf, *base;
+  size_t size, hdrsz;
+  int foreign_endian = 0;
+  int err;
+
+  libctf_init_debug();
+
+  if (ctfsect == NULL || ((symsect == NULL) != (strsect == NULL)))
+    return (ctf_set_open_errno (errp, EINVAL));
+
+  if (symsect != NULL && symsect->cts_entsize != sizeof (Elf32_Sym) &&
+      symsect->cts_entsize != sizeof (Elf64_Sym))
+    return (ctf_set_open_errno (errp, ECTF_SYMTAB));
+
+  if (symsect != NULL && symsect->cts_data == NULL)
+    return (ctf_set_open_errno (errp, ECTF_SYMBAD));
+
+  if (strsect != NULL && strsect->cts_data == NULL)
+    return (ctf_set_open_errno (errp, ECTF_STRBAD));
+
+  if (ctfsect->cts_size < sizeof (ctf_preamble_t))
+    return (ctf_set_open_errno (errp, ECTF_NOCTFBUF));
+
+  pp = (const ctf_preamble_t *) ctfsect->cts_data;
+
+  ctf_dprintf ("ctf_bufopen: magic=0x%x version=%u\n",
+	       pp->ctp_magic, pp->ctp_version);
+
+  /* Validate each part of the CTF header.
+
+     First, we validate the preamble (common to all versions).  At that point,
+     we know the endianness and specific header version, and can validate the
+     version-specific parts including section offsets and alignments.
+
+     We specifically do not support foreign-endian old versions.  */
+
+  if (_libctf_unlikely_ (pp->ctp_magic != CTF_MAGIC))
+    {
+      if (pp->ctp_magic == bswap_16 (CTF_MAGIC))
+	{
+	  if (pp->ctp_version != CTF_VERSION_3)
+	    return (ctf_set_open_errno (errp, ECTF_CTFVERS));
+	  foreign_endian = 1;
+	}
+      else
+	return (ctf_set_open_errno (errp, ECTF_NOCTFBUF));
+    }
+
+  if (_libctf_unlikely_ ((pp->ctp_version < CTF_VERSION_1)
+			 || (pp->ctp_version > CTF_VERSION_3)))
+    return (ctf_set_open_errno (errp, ECTF_CTFVERS));
+
+  if ((symsect != NULL) && (pp->ctp_version < CTF_VERSION_2))
+    {
+      /* The symtab can contain function entries which contain embedded ctf
+	 info.  We do not support dynamically upgrading such entries (none
+	 should exist in any case, since dwarf2ctf does not create them).  */
+
+      ctf_dprintf ("ctf_bufopen: CTF version %d symsect not "
+		   "supported\n", pp->ctp_version);
+      return (ctf_set_open_errno (errp, ECTF_NOTSUP));
+    }
+
+  if (ctfsect->cts_size < sizeof (ctf_header_t))
+    return (ctf_set_open_errno (errp, ECTF_NOCTFBUF));
+
+  memcpy (&hp, ctfsect->cts_data, sizeof (hp));
+
+  if (foreign_endian)
+    flip_header (&hp);
+
+  hdrsz = sizeof (ctf_header_t);
+
+  size = hp.cth_stroff + hp.cth_strlen;
+
+  ctf_dprintf ("ctf_bufopen: uncompressed size=%lu\n", (unsigned long) size);
+
+  if (hp.cth_lbloff > size || hp.cth_objtoff > size
+      || hp.cth_funcoff > size || hp.cth_typeoff > size || hp.cth_stroff > size)
+    return (ctf_set_open_errno (errp, ECTF_CORRUPT));
+
+  if (hp.cth_lbloff > hp.cth_objtoff
+      || hp.cth_objtoff > hp.cth_funcoff
+      || hp.cth_funcoff > hp.cth_typeoff
+      || hp.cth_funcoff > hp.cth_varoff
+      || hp.cth_varoff > hp.cth_typeoff || hp.cth_typeoff > hp.cth_stroff)
+    return (ctf_set_open_errno (errp, ECTF_CORRUPT));
+
+  if ((hp.cth_lbloff & 3) || (hp.cth_objtoff & 1)
+      || (hp.cth_funcoff & 1) || (hp.cth_varoff & 3) || (hp.cth_typeoff & 3))
+    return (ctf_set_open_errno (errp, ECTF_CORRUPT));
+
+  /* Once everything is determined to be valid, attempt to decompress the CTF
+     data buffer if it is compressed, or copy it into new storage if it is not
+     compressed but needs endian-flipping.  Otherwise we just put the data
+     section's buffer pointer into ctf_buf, below.  */
+
+  /* Note: if this is a v1 buffer, it will be reallocated and expanded by
+     init_types().  */
+
+  if (hp.cth_flags & CTF_F_COMPRESS)
+    {
+      size_t srclen, dstlen;
+      const void *src;
+      int rc = Z_OK;
+
+      if ((base = ctf_data_alloc (size + hdrsz)) == NULL)
+	return (ctf_set_open_errno (errp, ECTF_ZALLOC));
+
+      memcpy (base, ctfsect->cts_data, hdrsz);
+      ((ctf_preamble_t *) base)->ctp_flags &= ~CTF_F_COMPRESS;
+      buf = (unsigned char *) base + hdrsz;
+
+      src = (unsigned char *) ctfsect->cts_data + hdrsz;
+      srclen = ctfsect->cts_size - hdrsz;
+      dstlen = size;
+
+      if ((rc = uncompress (buf, &dstlen, src, srclen)) != Z_OK)
+	{
+	  ctf_dprintf ("zlib inflate err: %s\n", zError (rc));
+	  ctf_data_free (base, size + hdrsz);
+	  return (ctf_set_open_errno (errp, ECTF_DECOMPRESS));
+	}
+
+      if (dstlen != size)
+	{
+	  ctf_dprintf ("zlib inflate short -- got %lu of %lu "
+		       "bytes\n", (unsigned long) dstlen, (unsigned long) size);
+	  ctf_data_free (base, size + hdrsz);
+	  return (ctf_set_open_errno (errp, ECTF_CORRUPT));
+	}
+
+    }
+  else if (foreign_endian)
+    {
+      if ((base = ctf_data_alloc (size + hdrsz)) == NULL)
+	return (ctf_set_open_errno (errp, ECTF_ZALLOC));
+    }
+  else
+    {
+      base = (void *) ctfsect->cts_data;
+      buf = (unsigned char *) base + hdrsz;
+    }
+
+  /* Once we have uncompressed and validated the CTF data buffer, we can
+     proceed with allocating a ctf_file_t and initializing it.
+
+     Nothing that depends on buf or base should be set directly in this function
+     before the init_types() call, because it may be reallocated during
+     transparent upgrade if this recension of libctf is so configured: see
+     ctf_set_base() and ctf_realloc_base().  */
+
+  if ((fp = ctf_alloc (sizeof (ctf_file_t))) == NULL)
+    return (ctf_set_open_errno (errp, ENOMEM));
+
+  memset (fp, 0, sizeof (ctf_file_t));
+  ctf_set_version (fp, &hp, hp.cth_version);
+
+  if (_libctf_unlikely_ (hp.cth_version < CTF_VERSION_2))
+    fp->ctf_parmax = CTF_MAX_PTYPE_V1;
+  else
+    fp->ctf_parmax = CTF_MAX_PTYPE;
+
+  memcpy (&fp->ctf_data, ctfsect, sizeof (ctf_sect_t));
+
+  if (symsect != NULL)
+    {
+      memcpy (&fp->ctf_symtab, symsect, sizeof (ctf_sect_t));
+      memcpy (&fp->ctf_strtab, strsect, sizeof (ctf_sect_t));
+    }
+
+  if (fp->ctf_data.cts_name != NULL)
+    fp->ctf_data.cts_name = ctf_strdup (fp->ctf_data.cts_name);
+  if (fp->ctf_symtab.cts_name != NULL)
+    fp->ctf_symtab.cts_name = ctf_strdup (fp->ctf_symtab.cts_name);
+  if (fp->ctf_strtab.cts_name != NULL)
+    fp->ctf_strtab.cts_name = ctf_strdup (fp->ctf_strtab.cts_name);
+
+  if (fp->ctf_data.cts_name == NULL)
+    fp->ctf_data.cts_name = _CTF_NULLSTR;
+  if (fp->ctf_symtab.cts_name == NULL)
+    fp->ctf_symtab.cts_name = _CTF_NULLSTR;
+  if (fp->ctf_strtab.cts_name == NULL)
+    fp->ctf_strtab.cts_name = _CTF_NULLSTR;
+
+  if (strsect != NULL)
+    {
+      fp->ctf_str[CTF_STRTAB_1].cts_strs = strsect->cts_data;
+      fp->ctf_str[CTF_STRTAB_1].cts_len = strsect->cts_size;
+    }
+
+  if (foreign_endian &&
+      (err = flip_ctf (&hp, base)) != 0)
+    {
+      /* We can be certain that flip_ctf() will have endian-flipped everything
+         other than the types table when we return.  In particular the header
+         is fine, so set it, to allow freeing to use the usual code path.  */
+
+      (void) ctf_set_open_errno (errp, err);
+      ctf_set_base (fp, &hp, base);
+      goto bad;
+    }
+
+  ctf_set_base (fp, &hp, base);
+  fp->ctf_size = size + hdrsz;
+
+  if ((err = init_types (fp, &hp)) != 0)
+    {
+      (void) ctf_set_open_errno (errp, err);
+      goto bad;
+    }
+
+  /* The ctf region may have been reallocated by init_types(), but now
+     that is done, it will not move again, so we can protect it, as long
+     as it didn't come from the ctfsect, which might have been allocated
+     with malloc().  */
+
+  if (fp->ctf_base != (void *) ctfsect->cts_data)
+    ctf_data_protect ((void *) fp->ctf_base, fp->ctf_size);
+
+  /* If we have a symbol table section, allocate and initialize
+     the symtab translation table, pointed to by ctf_sxlate.  */
+
+  if (symsect != NULL)
+    {
+      fp->ctf_nsyms = symsect->cts_size / symsect->cts_entsize;
+      fp->ctf_sxlate = ctf_alloc (fp->ctf_nsyms * sizeof (uint32_t));
+
+      if (fp->ctf_sxlate == NULL)
+	{
+	  (void) ctf_set_open_errno (errp, ENOMEM);
+	  goto bad;
+	}
+
+      if ((err = init_symtab (fp, &hp, symsect, strsect)) != 0)
+	{
+	  (void) ctf_set_open_errno (errp, err);
+	  goto bad;
+	}
+    }
+
+  /* Initialize the ctf_lookup_by_name top-level dictionary.  We keep an
+     array of type name prefixes and the corresponding ctf_hash to use.
+     NOTE: This code must be kept in sync with the code in ctf_update().  */
+  fp->ctf_lookups[0].ctl_prefix = "struct";
+  fp->ctf_lookups[0].ctl_len = strlen (fp->ctf_lookups[0].ctl_prefix);
+  fp->ctf_lookups[0].ctl_hash = fp->ctf_structs;
+  fp->ctf_lookups[1].ctl_prefix = "union";
+  fp->ctf_lookups[1].ctl_len = strlen (fp->ctf_lookups[1].ctl_prefix);
+  fp->ctf_lookups[1].ctl_hash = fp->ctf_unions;
+  fp->ctf_lookups[2].ctl_prefix = "enum";
+  fp->ctf_lookups[2].ctl_len = strlen (fp->ctf_lookups[2].ctl_prefix);
+  fp->ctf_lookups[2].ctl_hash = fp->ctf_enums;
+  fp->ctf_lookups[3].ctl_prefix = _CTF_NULLSTR;
+  fp->ctf_lookups[3].ctl_len = strlen (fp->ctf_lookups[3].ctl_prefix);
+  fp->ctf_lookups[3].ctl_hash = fp->ctf_names;
+  fp->ctf_lookups[4].ctl_prefix = NULL;
+  fp->ctf_lookups[4].ctl_len = 0;
+  fp->ctf_lookups[4].ctl_hash = NULL;
+
+  if (symsect != NULL)
+    {
+      if (symsect->cts_entsize == sizeof (Elf64_Sym))
+	(void) ctf_setmodel (fp, CTF_MODEL_LP64);
+      else
+	(void) ctf_setmodel (fp, CTF_MODEL_ILP32);
+    }
+  else
+    (void) ctf_setmodel (fp, CTF_MODEL_NATIVE);
+
+  fp->ctf_refcnt = 1;
+  return fp;
+
+bad:
+  ctf_close (fp);
+  return NULL;
+}
+
+/* Close the specified CTF container and free associated data structures.  Note
+   that ctf_close() is a reference counted operation: if the specified file is
+   the parent of other active containers, its reference count will be greater
+   than one and it will be freed later when no active children exist.  */
+
+void
+ctf_close (ctf_file_t *fp)
+{
+  ctf_dtdef_t *dtd, *ntd;
+  ctf_dvdef_t *dvd, *nvd;
+
+  if (fp == NULL)
+    return;		   /* Allow ctf_close(NULL) to simplify caller code.  */
+
+  ctf_dprintf ("ctf_close(%p) refcnt=%u\n", (void *) fp, fp->ctf_refcnt);
+
+  if (fp->ctf_refcnt > 1)
+    {
+      fp->ctf_refcnt--;
+      return;
+    }
+
+  if (fp->ctf_dynparname != NULL)
+    ctf_free (fp->ctf_dynparname);
+
+  if (fp->ctf_parent != NULL)
+    ctf_close (fp->ctf_parent);
+
+  for (dtd = ctf_list_next (&fp->ctf_dtdefs); dtd != NULL; dtd = ntd)
+    {
+      ntd = ctf_list_next (dtd);
+      ctf_dtd_delete (fp, dtd);
+    }
+  ctf_dynhash_destroy (fp->ctf_dthash);
+  ctf_dynhash_destroy (fp->ctf_dtbyname);
+
+  for (dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL; dvd = nvd)
+    {
+      nvd = ctf_list_next (dvd);
+      ctf_dvd_delete (fp, dvd);
+    }
+  ctf_dynhash_destroy (fp->ctf_dvhash);
+
+  ctf_free (fp->ctf_tmp_typeslice);
+
+  if (fp->ctf_data.cts_name != _CTF_NULLSTR &&
+      fp->ctf_data.cts_name != NULL)
+    ctf_free ((char *) fp->ctf_data.cts_name);
+
+  if (fp->ctf_symtab.cts_name != _CTF_NULLSTR &&
+      fp->ctf_symtab.cts_name != NULL)
+    ctf_free ((char *) fp->ctf_symtab.cts_name);
+
+  if (fp->ctf_strtab.cts_name != _CTF_NULLSTR &&
+      fp->ctf_strtab.cts_name != NULL)
+    ctf_free ((char *) fp->ctf_strtab.cts_name);
+
+  if (fp->ctf_data_alloced)
+    free (fp->ctf_data_alloced);
+  else if (fp->ctf_data_mmapped)
+    ctf_munmap (fp->ctf_data_mmapped, fp->ctf_data_mmapped_len);
+
+  if (fp->ctf_symtab_alloced)
+    free (fp->ctf_symtab_alloced);
+
+  if (fp->ctf_strtab_alloced)
+    free (fp->ctf_strtab_alloced);
+
+  if (fp->ctf_bfd_close)
+    fp->ctf_bfd_close (fp);
+
+  ctf_free_base (fp, NULL, 0);
+
+  if (fp->ctf_sxlate != NULL)
+    ctf_free (fp->ctf_sxlate);
+
+  if (fp->ctf_txlate != NULL)
+    ctf_free (fp->ctf_txlate);
+
+  if (fp->ctf_ptrtab != NULL)
+    ctf_free (fp->ctf_ptrtab);
+
+  ctf_hash_destroy (fp->ctf_structs);
+  ctf_hash_destroy (fp->ctf_unions);
+  ctf_hash_destroy (fp->ctf_enums);
+  ctf_hash_destroy (fp->ctf_names);
+
+  ctf_free (fp);
+}
+
+/* Return the ctfsect out of the core ctf_impl.  Useful for freeing the
+   ctfsect's data * after ctf_close(), which is why we return the actual
+   structure, not a pointer to it, since that is likely to become a pointer to
+   freed data before the return value is used under the expected use case of
+   ctf_getsect()/ ctf_close()/free().  */
+extern ctf_sect_t
+ctf_getdatasect (const ctf_file_t *fp)
+{
+  return fp->ctf_data;
+}
+
+/* Return the CTF handle for the parent CTF container, if one exists.
+   Otherwise return NULL to indicate this container has no imported parent.  */
+ctf_file_t *
+ctf_parent_file (ctf_file_t *fp)
+{
+  return fp->ctf_parent;
+}
+
+/* Return the name of the parent CTF container, if one exists.  Otherwise
+   return NULL to indicate this container is a root container.  */
+const char *
+ctf_parent_name (ctf_file_t *fp)
+{
+  return fp->ctf_parname;
+}
+
+/* Set the parent name.  It is an error to call this routine without calling
+   ctf_import() at some point.  */
+void
+ctf_parent_name_set (ctf_file_t *fp, const char *name)
+{
+  if (fp->ctf_dynparname != NULL)
+    ctf_free (fp->ctf_dynparname);
+
+  fp->ctf_dynparname = ctf_strdup (name);
+  fp->ctf_parname = fp->ctf_dynparname;
+}
+
+/* Import the types from the specified parent container by storing a pointer
+   to it in ctf_parent and incrementing its reference count.  Only one parent
+   is allowed: if a parent already exists, it is replaced by the new parent.  */
+int
+ctf_import (ctf_file_t *fp, ctf_file_t *pfp)
+{
+  if (fp == NULL || fp == pfp || (pfp != NULL && pfp->ctf_refcnt == 0))
+    return (ctf_set_errno (fp, EINVAL));
+
+  if (pfp != NULL && pfp->ctf_dmodel != fp->ctf_dmodel)
+    return (ctf_set_errno (fp, ECTF_DMODEL));
+
+  if (fp->ctf_parent != NULL)
+    ctf_close (fp->ctf_parent);
+
+  if (pfp != NULL)
+    {
+      fp->ctf_flags |= LCTF_CHILD;
+      pfp->ctf_refcnt++;
+
+      if (fp->ctf_parname == NULL)
+	ctf_parent_name_set (fp, "PARENT");
+    }
+  fp->ctf_parent = pfp;
+  return 0;
+}
+
+/* Set the data model constant for the CTF container.  */
+int
+ctf_setmodel (ctf_file_t *fp, int model)
+{
+  const ctf_dmodel_t *dp;
+
+  for (dp = _libctf_models; dp->ctd_name != NULL; dp++)
+    {
+      if (dp->ctd_code == model)
+	{
+	  fp->ctf_dmodel = dp;
+	  return 0;
+	}
+    }
+
+  return (ctf_set_errno (fp, EINVAL));
+}
+
+/* Return the data model constant for the CTF container.  */
+int
+ctf_getmodel (ctf_file_t *fp)
+{
+  return fp->ctf_dmodel->ctd_code;
+}
+
+void
+ctf_setspecific (ctf_file_t *fp, void *data)
+{
+  fp->ctf_specific = data;
+}
+
+void *
+ctf_getspecific (ctf_file_t *fp)
+{
+  return fp->ctf_specific;
+}
diff --git a/libctf/swap.h b/libctf/swap.h
new file mode 100644
index 0000000000..06a9330181
--- /dev/null
+++ b/libctf/swap.h
@@ -0,0 +1,60 @@
+/* Interface to byteswapping functions.
+   Copyright (C) 2006-2019 Free Software Foundation, Inc.
+
+   This file is part of libctf.
+
+   libctf is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+   See the GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _CTF_SWAP_H
+#define _CTF_SWAP_H
+
+#include "config.h"
+#include <stdint.h>
+
+#ifdef HAVE_BYTESWAP_H
+#include <byteswap.h>
+#else
+
+/* Provide our own versions of the byteswap functions.  */
+inline uint16_t
+bswap_16(uint16_t v)
+{
+  return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
+}
+
+inline uint32_t
+bswap_32(uint32_t v)
+{
+  return (  ((v & 0xff000000) >> 24)
+	  | ((v & 0x00ff0000) >>  8)
+	  | ((v & 0x0000ff00) <<  8)
+	  | ((v & 0x000000ff) << 24));
+}
+
+inline uint64_t
+bswap_64(uint64_t v)
+{
+  return (  ((v & 0xff00000000000000ULL) >> 56)
+	  | ((v & 0x00ff000000000000ULL) >> 40)
+	  | ((v & 0x0000ff0000000000ULL) >> 24)
+	  | ((v & 0x000000ff00000000ULL) >>  8)
+	  | ((v & 0x00000000ff000000ULL) <<  8)
+	  | ((v & 0x0000000000ff0000ULL) << 24)
+	  | ((v & 0x000000000000ff00ULL) << 40)
+	  | ((v & 0x00000000000000ffULL) << 56));
+}
+#endif /* !defined(HAVE_BYTESWAP_H) */
+
+#endif /* !defined(_CTF_SWAP_H) */
-- 
2.21.0.237.gd0cfaa883d

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v2 05/19] libctf: error handling
  2019-05-17 22:10 [PATCH v2 00/19] libctf, and CTF support for objdump and readelf Nick Alcock
  2019-05-17 22:10 ` [PATCH v2 12/19] libctf: lookups by name and symbol Nick Alcock
@ 2019-05-17 22:10 ` Nick Alcock
  2019-05-17 22:10 ` [PATCH v2 17/19] libctf: debug dumping Nick Alcock
                   ` (18 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nick Alcock @ 2019-05-17 22:10 UTC (permalink / raw)
  To: binutils

CTF functions return zero on success or an extended errno value which
can be translated into a string via the functions in this commit.

The errno numbers start at -CTF_BASE.

Changes from v1:
 - Correct erroneous license (GPLv2+ -> v3+) and reset copyright years.
 - Unused errors are now named starting ECTF_UNUSED.

libctf/
	* ctf-error.c: New file.

include/
	* ctf-api.h (ctf_errno): New declaration.
	(ctf_errmsg): Likewise.
---
 include/ctf-api.h  |  2 +
 libctf/ctf-error.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 95 insertions(+)
 create mode 100644 libctf/ctf-error.c

diff --git a/include/ctf-api.h b/include/ctf-api.h
index aab85192ca..81ec5c6522 100644
--- a/include/ctf-api.h
+++ b/include/ctf-api.h
@@ -122,6 +122,8 @@ enum
 #define	CTF_ADD_NONROOT	0	/* Type only visible in nested scope.  */
 #define	CTF_ADD_ROOT	1	/* Type visible at top-level scope.  */
 
+extern int ctf_errno (ctf_file_t *);
+extern const char *ctf_errmsg (int);
 
 extern void ctf_setdebug (int debug);
 extern int ctf_getdebug (void);
diff --git a/libctf/ctf-error.c b/libctf/ctf-error.c
new file mode 100644
index 0000000000..a0e1f28100
--- /dev/null
+++ b/libctf/ctf-error.c
@@ -0,0 +1,93 @@
+/* Error table.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+
+   This file is part of libctf.
+
+   libctf is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+   See the GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <ctf-impl.h>
+
+static const char *const _ctf_errlist[] = {
+  "File is not in CTF or ELF format",		     /* ECTF_FMT */
+  "BFD error",					     /* ECTF_BFDERR */
+  "File uses more recent CTF version than libctf",   /* ECTF_CTFVERS */
+  "Unused error",				     /* ECTF_UNUSED1 */
+  "Symbol table uses invalid entry size",	     /* ECTF_SYMTAB */
+  "Symbol table data buffer is not valid",	     /* ECTF_SYMBAD */
+  "String table data buffer is not valid",	     /* ECTF_STRBAD */
+  "File data structure corruption detected",	     /* ECTF_CORRUPT */
+  "File does not contain CTF data",		     /* ECTF_NOCTFDATA */
+  "Buffer does not contain CTF data",		     /* ECTF_NOCTFBUF */
+  "Symbol table information is not available",	     /* ECTF_NOSYMTAB */
+  "Type information is in parent and unavailable",   /* ECTF_NOPARENT */
+  "Cannot import types with different data model",   /* ECTF_DMODEL */
+  "Unused error",				     /* ECTF_UNUSED2 */
+  "Failed to allocate (de)compression buffer",	     /* ECTF_ZALLOC */
+  "Failed to decompress CTF data",		     /* ECTF_DECOMPRESS */
+  "External string table is not available",	     /* ECTF_STRTAB */
+  "String name offset is corrupt",		     /* ECTF_BADNAME */
+  "Invalid type identifier",			     /* ECTF_BADID */
+  "Type is not a struct or union",		     /* ECTF_NOTSOU */
+  "Type is not an enum",			     /* ECTF_NOTENUM */
+  "Type is not a struct, union, or enum",	     /* ECTF_NOTSUE */
+  "Type is not an integer, float, or enum",	     /* ECTF_NOTINTFP */
+  "Type is not an array",			     /* ECTF_NOTARRAY */
+  "Type does not reference another type",	     /* ECTF_NOTREF */
+  "Input buffer is too small for type name",	     /* ECTF_NAMELEN */
+  "No type information available for that name",     /* ECTF_NOTYPE */
+  "Syntax error in type name",			     /* ECTF_SYNTAX */
+  "Symbol table entry is not a function",	     /* ECTF_NOTFUNC */
+  "No function information available for symbol",    /* ECTF_NOFUNCDAT */
+  "Symbol table entry is not a data object",	     /* ECTF_NOTDATA */
+  "No type information available for symbol",	     /* ECTF_NOTYPEDAT */
+  "No label information available for that name",    /* ECTF_NOLABEL */
+  "File does not contain any labels",		     /* ECTF_NOLABELDATA */
+  "Feature not supported",			     /* ECTF_NOTSUP */
+  "Invalid enum element name",			     /* ECTF_NOENUMNAM */
+  "Invalid member name",			     /* ECTF_NOMEMBNAM */
+  "CTF container is read-only",			     /* ECTF_RDONLY */
+  "Limit on number of dynamic type members reached", /* ECTF_DTFULL */
+  "Limit on number of dynamic types reached",	     /* ECTF_FULL */
+  "Duplicate member or variable name",		     /* ECTF_DUPLICATE */
+  "Conflicting type is already defined",	     /* ECTF_CONFLICT */
+  "Attempt to roll back past a ctf_update",	     /* ECTF_OVERROLLBACK */
+  "Failed to compress CTF data",		     /* ECTF_COMPRESS */
+  "Failed to create CTF archive",		     /* ECTF_ARCREATE */
+  "Name not found in CTF archive",		     /* ECTF_ARNNAME */
+  "Overflow of type bitness or offset in slice",     /* ECTF_SLICEOVERFLOW */
+  "Unknown section number in dump",		     /* ECTF_DUMPSECTUNKNOWN */
+  "Section changed in middle of dump"		     /* ECTF_DUMPSECTCHANGED */
+};
+
+static const int _ctf_nerr = sizeof (_ctf_errlist) / sizeof (_ctf_errlist[0]);
+
+const char *
+ctf_errmsg (int error)
+{
+  const char *str;
+
+  if (error >= ECTF_BASE && (error - ECTF_BASE) < _ctf_nerr)
+    str = _ctf_errlist[error - ECTF_BASE];
+  else
+    str = ctf_strerror (error);
+
+  return (str ? str : "Unknown error");
+}
+
+int
+ctf_errno (ctf_file_t * fp)
+{
+  return fp->ctf_errno;
+}
-- 
2.21.0.237.gd0cfaa883d

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v2 07/19] libctf: implementation definitions related to file creation
  2019-05-17 22:10 [PATCH v2 00/19] libctf, and CTF support for objdump and readelf Nick Alcock
                   ` (3 preceding siblings ...)
  2019-05-17 22:10 ` [PATCH v2 01/19] include: new header ctf.h: file format description Nick Alcock
@ 2019-05-17 22:10 ` Nick Alcock
  2019-05-17 22:10 ` [PATCH v2 03/19] libctf: lowest-level memory allocation and debug-dumping wrappers Nick Alcock
                   ` (15 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nick Alcock @ 2019-05-17 22:10 UTC (permalink / raw)
  To: binutils

We now enter a series of commits that are sufficiently tangled that
avoiding forward definitions is almost impossible: no attempt is made to
make individual commits compilable (which is why the build system does
not reference any of them yet): the only important thing is that they
should form something like conceptual groups.

But first, some definitions, including the core ctf_file_t itself.  Uses
of these definitions will be introduced in later commits.

Changes from v1:
 - Correct erroneous license (GPLv2+ -> v3+) and reset copyright years.
 - Drop LCTF_MMAP: seemingly not supportable with bfd (which is
   unfortunate)
 - Move some of the prototype introduction in ctf-impl.h to later in the
   series

libctf/
	* ctf-impl.h: New definitions and declarations for type creation
	and lookup.
---
 libctf/ctf-impl.h | 213 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 213 insertions(+)

diff --git a/libctf/ctf-impl.h b/libctf/ctf-impl.h
index cae31ec78f..53d062745a 100644
--- a/libctf/ctf-impl.h
+++ b/libctf/ctf-impl.h
@@ -63,12 +63,209 @@ extern "C"
 typedef struct ctf_fixed_hash ctf_hash_t; /* Private to ctf-hash.c.  */
 typedef struct ctf_dynhash ctf_dynhash_t; /* Private to ctf-hash.c.  */
 
+typedef struct ctf_strs
+{
+  const char *cts_strs;		/* Base address of string table.  */
+  size_t cts_len;		/* Size of string table in bytes.  */
+} ctf_strs_t;
+
+typedef struct ctf_dmodel
+{
+  const char *ctd_name;		/* Data model name.  */
+  int ctd_code;			/* Data model code.  */
+  size_t ctd_pointer;		/* Size of void * in bytes.  */
+  size_t ctd_char;		/* Size of char in bytes.  */
+  size_t ctd_short;		/* Size of short in bytes.  */
+  size_t ctd_int;		/* Size of int in bytes.  */
+  size_t ctd_long;		/* Size of long in bytes.  */
+} ctf_dmodel_t;
+
+typedef struct ctf_lookup
+{
+  const char *ctl_prefix;	/* String prefix for this lookup.  */
+  size_t ctl_len;		/* Length of prefix string in bytes.  */
+  ctf_hash_t *ctl_hash;		/* Pointer to hash table for lookup.  */
+} ctf_lookup_t;
+
+typedef struct ctf_fileops
+{
+  uint32_t (*ctfo_get_kind) (uint32_t);
+  uint32_t (*ctfo_get_root) (uint32_t);
+  uint32_t (*ctfo_get_vlen) (uint32_t);
+  ssize_t (*ctfo_get_ctt_size) (const ctf_file_t *, const ctf_type_t *,
+				ssize_t *, ssize_t *);
+  ssize_t (*ctfo_get_vbytes) (unsigned short, ssize_t, size_t);
+} ctf_fileops_t;
+
 typedef struct ctf_list
 {
   struct ctf_list *l_prev;	/* Previous pointer or tail pointer.  */
   struct ctf_list *l_next;	/* Next pointer or head pointer.  */
 } ctf_list_t;
 
+typedef enum
+  {
+   CTF_PREC_BASE,
+   CTF_PREC_POINTER,
+   CTF_PREC_ARRAY,
+   CTF_PREC_FUNCTION,
+   CTF_PREC_MAX
+  } ctf_decl_prec_t;
+
+typedef struct ctf_decl_node
+{
+  ctf_list_t cd_list;		/* Linked list pointers.  */
+  ctf_id_t cd_type;		/* Type identifier.  */
+  uint32_t cd_kind;		/* Type kind.  */
+  uint32_t cd_n;		/* Type dimension if array.  */
+} ctf_decl_node_t;
+
+typedef struct ctf_decl
+{
+  ctf_list_t cd_nodes[CTF_PREC_MAX]; /* Declaration node stacks.  */
+  int cd_order[CTF_PREC_MAX];	     /* Storage order of decls.  */
+  ctf_decl_prec_t cd_qualp;	     /* Qualifier precision.  */
+  ctf_decl_prec_t cd_ordp;	     /* Ordered precision.  */
+  char *cd_buf;			     /* Buffer for output.  */
+  int cd_err;			     /* Saved error value.  */
+  int cd_enomem;		     /* Nonzero if OOM during printing.  */
+} ctf_decl_t;
+
+typedef struct ctf_dmdef
+{
+  ctf_list_t dmd_list;		/* List forward/back pointers.  */
+  char *dmd_name;		/* Name of this member.  */
+  ctf_id_t dmd_type;		/* Type of this member (for sou).  */
+  unsigned long dmd_offset;	/* Offset of this member in bits (for sou).  */
+  int dmd_value;		/* Value of this member (for enum).  */
+} ctf_dmdef_t;
+
+typedef struct ctf_dtdef
+{
+  ctf_list_t dtd_list;		/* List forward/back pointers.  */
+  char *dtd_name;		/* Name associated with definition (if any).  */
+  ctf_id_t dtd_type;		/* Type identifier for this definition.  */
+  ctf_type_t dtd_data;		/* Type node (see <ctf.h>).  */
+  union
+  {
+    ctf_list_t dtu_members;	/* struct, union, or enum */
+    ctf_arinfo_t dtu_arr;	/* array */
+    ctf_encoding_t dtu_enc;	/* integer or float */
+    ctf_id_t *dtu_argv;		/* function */
+    ctf_slice_t dtu_slice;	/* slice */
+  } dtd_u;
+} ctf_dtdef_t;
+
+typedef struct ctf_dvdef
+{
+  ctf_list_t dvd_list;		/* List forward/back pointers.  */
+  char *dvd_name;		/* Name associated with variable.  */
+  ctf_id_t dvd_type;		/* Type of variable.  */
+  unsigned long dvd_snapshots;	/* Snapshot count when inserted.  */
+} ctf_dvdef_t;
+
+typedef struct ctf_bundle
+{
+  ctf_file_t *ctb_file;		/* CTF container handle.  */
+  ctf_id_t ctb_type;		/* CTF type identifier.  */
+  ctf_dtdef_t *ctb_dtd;		/* CTF dynamic type definition (if any).  */
+} ctf_bundle_t;
+
+/* The ctf_file is the structure used to represent a CTF container to library
+   clients, who see it only as an opaque pointer.  Modifications can therefore
+   be made freely to this structure without regard to client versioning.  The
+   ctf_file_t typedef appears in <ctf-api.h> and declares a forward tag.
+
+   NOTE: ctf_update() requires that everything inside of ctf_file either be an
+   immediate value, a pointer to dynamically allocated data *outside* of the
+   ctf_file itself, or a pointer to statically allocated data.  If you add a
+   pointer to ctf_file that points to something within the ctf_file itself,
+   you must make corresponding changes to ctf_update().  */
+
+struct ctf_file
+{
+  const ctf_fileops_t *ctf_fileops; /* Version-specific file operations.  */
+  ctf_sect_t ctf_data;		    /* CTF data from object file.  */
+  ctf_sect_t ctf_symtab;	    /* Symbol table from object file.  */
+  ctf_sect_t ctf_strtab;	    /* String table from object file.  */
+  ctf_hash_t *ctf_structs;	    /* Hash table of struct types.  */
+  ctf_hash_t *ctf_unions;	    /* Hash table of union types.  */
+  ctf_hash_t *ctf_enums;	    /* Hash table of enum types.  */
+  ctf_hash_t *ctf_names;	    /* Hash table of remaining type names.  */
+  ctf_lookup_t ctf_lookups[5];	    /* Pointers to hashes for name lookup.  */
+  ctf_strs_t ctf_str[2];	    /* Array of string table base and bounds.  */
+  const unsigned char *ctf_base;  /* Base of CTF header + uncompressed buffer.  */
+  const unsigned char *ctf_buf;	  /* Uncompressed CTF data buffer.  */
+  size_t ctf_size;		  /* Size of CTF header + uncompressed data.  */
+  uint32_t *ctf_sxlate;		  /* Translation table for symtab entries.  */
+  unsigned long ctf_nsyms;	  /* Number of entries in symtab xlate table.  */
+  uint32_t *ctf_txlate;		  /* Translation table for type IDs.  */
+  uint32_t *ctf_ptrtab;		  /* Translation table for pointer-to lookups.  */
+  struct ctf_varent *ctf_vars;	  /* Sorted variable->type mapping.  */
+  unsigned long ctf_nvars;	  /* Number of variables in ctf_vars.  */
+  unsigned long ctf_typemax;	  /* Maximum valid type ID number.  */
+  const ctf_dmodel_t *ctf_dmodel; /* Data model pointer (see above).  */
+  struct ctf_file *ctf_parent;	  /* Parent CTF container (if any).  */
+  const char *ctf_parlabel;	  /* Label in parent container (if any).  */
+  const char *ctf_parname;	  /* Basename of parent (if any).  */
+  char *ctf_dynparname;		  /* Dynamically allocated name of parent.  */
+  uint32_t ctf_parmax;		  /* Highest type ID of a parent type.  */
+  uint32_t ctf_refcnt;		  /* Reference count (for parent links).  */
+  uint32_t ctf_flags;		  /* Libctf flags (see below).  */
+  int ctf_errno;		  /* Error code for most recent error.  */
+  int ctf_version;		  /* CTF data version.  */
+  ctf_dynhash_t *ctf_dthash;	  /* Hash of dynamic type definitions.  */
+  ctf_dynhash_t *ctf_dtbyname;	  /* DTDs, indexed by name.  */
+  ctf_list_t ctf_dtdefs;	  /* List of dynamic type definitions.  */
+  ctf_dynhash_t *ctf_dvhash;	  /* Hash of dynamic variable mappings.  */
+  ctf_list_t ctf_dvdefs;	  /* List of dynamic variable definitions.  */
+  size_t ctf_dtvstrlen;		  /* Total length of dynamic type+var strings.  */
+  unsigned long ctf_dtnextid;	  /* Next dynamic type id to assign.  */
+  unsigned long ctf_dtoldid;	  /* Oldest id that has been committed.  */
+  unsigned long ctf_snapshots;	  /* ctf_snapshot() plus ctf_update() count.  */
+  unsigned long ctf_snapshot_lu;  /* ctf_snapshot() call count at last update.  */
+  char *ctf_tmp_typeslice;	  /* Storage for slicing up type names.  */
+  size_t ctf_tmp_typeslicelen;	  /* Size of the typeslice.  */
+  void *ctf_specific;		  /* Data for ctf_get/setspecific().  */
+};
+
+/* Return x rounded up to an alignment boundary.
+   eg, P2ROUNDUP(0x1234, 0x100) == 0x1300 (0x13*align)
+   eg, P2ROUNDUP(0x5600, 0x100) == 0x5600 (0x56*align)  */
+#define P2ROUNDUP(x, align)		(-(-(x) & -(align)))
+
+/* * If an offs is not aligned already then round it up and align it. */
+#define LCTF_ALIGN_OFFS(offs, align) ((offs + (align - 1)) & ~(align - 1))
+
+#define LCTF_TYPE_ISPARENT(fp, id) ((id) <= fp->ctf_parmax)
+#define LCTF_TYPE_ISCHILD(fp, id) ((id) > fp->ctf_parmax)
+#define LCTF_TYPE_TO_INDEX(fp, id) ((id) & (fp->ctf_parmax))
+#define LCTF_INDEX_TO_TYPE(fp, id, child) (child ? ((id) | (fp->ctf_parmax+1)) : \
+					   (id))
+
+#define LCTF_INDEX_TO_TYPEPTR(fp, i) \
+  ((ctf_type_t *)((uintptr_t)(fp)->ctf_buf + (fp)->ctf_txlate[(i)]))
+
+#define LCTF_INFO_KIND(fp, info)	((fp)->ctf_fileops->ctfo_get_kind(info))
+#define LCTF_INFO_ISROOT(fp, info)	((fp)->ctf_fileops->ctfo_get_root(info))
+#define LCTF_INFO_VLEN(fp, info)	((fp)->ctf_fileops->ctfo_get_vlen(info))
+#define LCTF_VBYTES(fp, kind, size, vlen) \
+  ((fp)->ctf_fileops->ctfo_get_vbytes(kind, size, vlen))
+
+static inline ssize_t ctf_get_ctt_size (const ctf_file_t *fp,
+					const ctf_type_t *tp,
+					ssize_t *sizep,
+					ssize_t *incrementp)
+{
+  return (fp->ctf_fileops->ctfo_get_ctt_size (fp, tp, sizep, incrementp));
+}
+
+#define LCTF_CHILD	0x0001	/* CTF container is a child */
+#define LCTF_RDWR	0x0002	/* CTF container is writable */
+#define LCTF_DIRTY	0x0004	/* CTF container has been modified */
+
+extern const ctf_type_t *ctf_lookup_by_id (ctf_file_t **, ctf_id_t);
+
 typedef unsigned int (*ctf_hash_fun) (const void *ptr);
 extern unsigned int ctf_hash_integer (const void *ptr);
 extern unsigned int ctf_hash_string (const void *ptr);
@@ -100,6 +297,15 @@ extern void ctf_list_append (ctf_list_t *, void *);
 extern void ctf_list_prepend (ctf_list_t *, void *);
 extern void ctf_list_delete (ctf_list_t *, void *);
 
+extern void ctf_dtd_insert (ctf_file_t *, ctf_dtdef_t *);
+extern void ctf_dtd_delete (ctf_file_t *, ctf_dtdef_t *);
+extern ctf_dtdef_t *ctf_dtd_lookup (const ctf_file_t *, ctf_id_t);
+extern ctf_dtdef_t *ctf_dynamic_type (const ctf_file_t *, ctf_id_t);
+
+extern void ctf_dvd_insert (ctf_file_t *, ctf_dvdef_t *);
+extern void ctf_dvd_delete (ctf_file_t *, ctf_dvdef_t *);
+extern ctf_dvdef_t *ctf_dvd_lookup (const ctf_file_t *, const char *);
+
 extern const char *ctf_strraw (ctf_file_t *, uint32_t);
 extern const char *ctf_strptr (ctf_file_t *, uint32_t);
 
@@ -125,12 +331,19 @@ extern char *ctf_strdup (const char *);
 extern char *ctf_str_append (char *, const char *);
 extern const char *ctf_strerror (int);
 
+extern ctf_id_t ctf_type_resolve_unsliced (ctf_file_t *, ctf_id_t);
+extern int ctf_type_kind_unsliced (ctf_file_t *, ctf_id_t);
+
 _libctf_printflike_ (1, 2)
 extern void ctf_dprintf (const char *, ...);
 extern void libctf_init_debug (void);
 
 extern Elf64_Sym *ctf_sym_to_elf64 (const Elf32_Sym *src, Elf64_Sym *dst);
 
+/* Variables, all underscore-prepended. */
+
+extern const char _CTF_NULLSTR[];	/* empty string */
+
 extern int _libctf_debug;	/* debugging messages enabled */
 
 #ifdef	__cplusplus
-- 
2.21.0.237.gd0cfaa883d

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v2 06/19] libctf: hashing
  2019-05-17 22:10 [PATCH v2 00/19] libctf, and CTF support for objdump and readelf Nick Alcock
                   ` (5 preceding siblings ...)
  2019-05-17 22:10 ` [PATCH v2 03/19] libctf: lowest-level memory allocation and debug-dumping wrappers Nick Alcock
@ 2019-05-17 22:10 ` Nick Alcock
  2019-05-17 22:10 ` [PATCH v2 19/19] binutils: CTF support for objdump and readelf Nick Alcock
                   ` (13 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nick Alcock @ 2019-05-17 22:10 UTC (permalink / raw)
  To: binutils

libctf maintains two distinct hash ADTs, one (ctf_dynhash) for wrapping
dynamically-generated unknown-sized hashes during CTF file construction,
one (ctf_hash) for wrapping unchanging hashes whose size is known at
creation time for reading CTF files that were previously created.

In the binutils implementation, these are both fairly thin wrappers
around libiberty hashtab.

Unusually, this code is not kept synchronized with libdtrace-ctf,
due to its dependence on libiberty hashtab.

Changes from v1:
 - Correct erroneous license (GPLv2+ -> v3+) and reset copyright years.

libctf/
	* ctf-hash.c: New file.
	* ctf-impl.h: New declarations.
---
 libctf/ctf-hash.c | 277 ++++++++++++++++++++++++++++++++++++++++++++++
 libctf/ctf-impl.h |  29 +++++
 2 files changed, 306 insertions(+)
 create mode 100644 libctf/ctf-hash.c

diff --git a/libctf/ctf-hash.c b/libctf/ctf-hash.c
new file mode 100644
index 0000000000..adfe93e5c0
--- /dev/null
+++ b/libctf/ctf-hash.c
@@ -0,0 +1,277 @@
+/* Interface to hashtable implementations.
+   Copyright (C) 2006-2019 Free Software Foundation, Inc.
+
+   This file is part of libctf.
+
+   libctf is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+   See the GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <ctf-impl.h>
+#include <string.h>
+#include "libiberty.h"
+#include "hashtab.h"
+
+/* We have two hashtable implementations: one, ctf_dynhash_*(), is an interface to
+   a dynamically-expanding hash with unknown size that should support addition
+   of large numbers of items, and removal as well, and is used only at
+   type-insertion time; the other, ctf_dynhash_*(), is an interface to a
+   fixed-size hash from const char * -> ctf_id_t with number of elements
+   specified at creation time, that should support addition of items but need
+   not support removal.  These can be implemented by the same underlying hashmap
+   if you wish.  */
+
+typedef struct ctf_helem
+{
+  void *key;			 /* Either a pointer, or a coerced ctf_id_t.  */
+  void *value;			 /* The value (possibly a coerced int).  */
+  ctf_hash_free_fun key_free;
+  ctf_hash_free_fun value_free;
+} ctf_helem_t;
+
+struct ctf_dynhash
+{
+  struct htab *htab;
+  ctf_hash_free_fun key_free;
+  ctf_hash_free_fun value_free;
+};
+
+/* Hash functions. */
+
+unsigned int
+ctf_hash_integer (const void *ptr)
+{
+  ctf_helem_t *hep = (ctf_helem_t *) ptr;
+
+  return htab_hash_pointer (hep->key);
+}
+
+int
+ctf_hash_eq_integer (const void *a, const void *b)
+{
+  ctf_helem_t *hep_a = (ctf_helem_t *) a;
+  ctf_helem_t *hep_b = (ctf_helem_t *) b;
+
+  return htab_eq_pointer (hep_a->key, hep_b->key);
+}
+
+unsigned int
+ctf_hash_string (const void *ptr)
+{
+  ctf_helem_t *hep = (ctf_helem_t *) ptr;
+
+  return htab_hash_string (hep->key);
+}
+
+int
+ctf_hash_eq_string (const void *a, const void *b)
+{
+  ctf_helem_t *hep_a = (ctf_helem_t *) a;
+  ctf_helem_t *hep_b = (ctf_helem_t *) b;
+
+  return !strcmp((const char *) hep_a->key, (const char *) hep_b->key);
+}
+
+/* The dynhash, used for hashes whose size is not known at creation time. */
+
+/* Free a single ctf_helem.  */
+
+static void
+ctf_dynhash_item_free (void *item)
+{
+  ctf_helem_t *helem = item;
+
+  if (helem->key_free && helem->key)
+    helem->key_free (helem->key);
+  if (helem->value_free && helem->value)
+    helem->value_free (helem->value);
+  free (helem);
+}
+
+ctf_dynhash_t *
+ctf_dynhash_create (ctf_hash_fun hash_fun, ctf_hash_eq_fun eq_fun,
+                    ctf_hash_free_fun key_free, ctf_hash_free_fun value_free)
+{
+  ctf_dynhash_t *dynhash;
+
+  dynhash = malloc (sizeof (ctf_dynhash_t));
+  if (!dynhash)
+    return NULL;
+
+  /* 7 is arbitrary and untested for now..  */
+  if ((dynhash->htab = htab_create_alloc (7, (htab_hash) hash_fun, eq_fun,
+                                          ctf_dynhash_item_free, xcalloc, free)) == NULL)
+    {
+      free (dynhash);
+      return NULL;
+    }
+
+  dynhash->key_free = key_free;
+  dynhash->value_free = value_free;
+
+  return dynhash;
+}
+
+static ctf_helem_t **
+ctf_hashtab_lookup (struct htab *htab, const void *key, enum insert_option insert)
+{
+  ctf_helem_t tmp = { .key = (void *) key };
+  return (ctf_helem_t **) htab_find_slot (htab, &tmp, insert);
+}
+
+static ctf_helem_t *
+ctf_hashtab_insert (struct htab *htab, void *key, void *value)
+{
+  ctf_helem_t **slot;
+
+  slot = ctf_hashtab_lookup (htab, key, INSERT);
+
+  if (!slot)
+    {
+      errno = -ENOMEM;
+      return NULL;
+    }
+
+  if (!*slot)
+    {
+      *slot = malloc (sizeof (ctf_helem_t));
+      if (!*slot)
+	return NULL;
+      (*slot)->key = key;
+    }
+  (*slot)->value = value;
+  return *slot;
+}
+
+int
+ctf_dynhash_insert (ctf_dynhash_t *hp, void *key, void *value)
+{
+  ctf_helem_t *slot;
+
+  slot = ctf_hashtab_insert (hp->htab, key, value);
+
+  if (!slot)
+    return errno;
+
+  /* We need to keep the key_free and value_free around in each item because the
+     del function has no visiblity into the hash as a whole, only into the
+     individual items.  */
+
+  slot->key_free = hp->key_free;
+  slot->value_free = hp->value_free;
+
+  return 0;
+}
+
+void
+ctf_dynhash_remove (ctf_dynhash_t *hp, const void *key)
+{
+  htab_remove_elt (hp->htab, (void *) key);
+}
+
+void *
+ctf_dynhash_lookup (ctf_dynhash_t *hp, const void *key)
+{
+  ctf_helem_t **slot;
+
+  slot = ctf_hashtab_lookup (hp->htab, key, NO_INSERT);
+
+  if (slot)
+    return (*slot)->value;
+
+  return NULL;
+}
+
+void
+ctf_dynhash_destroy (ctf_dynhash_t *hp)
+{
+  if (hp != NULL)
+    htab_delete (hp->htab);
+  free (hp);
+}
+
+/* ctf_hash, used for fixed-size maps from const char * -> ctf_id_t without
+   removal.  This is a straight cast of a hashtab.  */
+
+ctf_hash_t *
+ctf_hash_create (unsigned long nelems, ctf_hash_fun hash_fun,
+		 ctf_hash_eq_fun eq_fun)
+{
+  return (ctf_hash_t *) htab_create_alloc (nelems, (htab_hash) hash_fun,
+					   eq_fun, free, xcalloc, free);
+}
+
+uint32_t
+ctf_hash_size (const ctf_hash_t *hp)
+{
+  return htab_elements ((struct htab *) hp);
+}
+
+int
+ctf_hash_insert_type (ctf_hash_t *hp, ctf_file_t *fp, uint32_t type,
+		      uint32_t name)
+{
+  ctf_strs_t *ctsp = &fp->ctf_str[CTF_NAME_STID (name)];
+  const char *str = ctsp->cts_strs + CTF_NAME_OFFSET (name);
+
+  if (type == 0)
+    return EINVAL;
+
+  if (ctsp->cts_strs == NULL)
+    return ECTF_STRTAB;
+
+  if (ctsp->cts_len <= CTF_NAME_OFFSET (name))
+    return ECTF_BADNAME;
+
+  if (str[0] == '\0')
+    return 0;		   /* Just ignore empty strings on behalf of caller.  */
+
+  if (ctf_hashtab_insert ((struct htab *) hp, (char *) str,
+			  (void *) (ptrdiff_t) type) != NULL)
+    return 0;
+  return errno;
+}
+
+/* if the key is already in the hash, override the previous definition with
+   this new official definition. If the key is not present, then call
+   ctf_hash_insert_type() and hash it in.  */
+int
+ctf_hash_define_type (ctf_hash_t *hp, ctf_file_t *fp, uint32_t type,
+                      uint32_t name)
+{
+  /* This matches the semantics of ctf_hash_insert_type() in this
+     implementation anyway.  */
+
+  return ctf_hash_insert_type (hp, fp, type, name);
+}
+
+ctf_id_t
+ctf_hash_lookup_type (ctf_hash_t *hp, ctf_file_t *fp __attribute__ ((__unused__)),
+		      const char *key)
+{
+  ctf_helem_t **slot;
+
+  slot = ctf_hashtab_lookup ((struct htab *) hp, key, NO_INSERT);
+
+  if (slot)
+    return (ctf_id_t) ((*slot)->value);
+
+  return 0;
+}
+
+void
+ctf_hash_destroy (ctf_hash_t *hp)
+{
+  if (hp != NULL)
+    htab_delete ((struct htab *) hp);
+}
diff --git a/libctf/ctf-impl.h b/libctf/ctf-impl.h
index ca5397f9c7..cae31ec78f 100644
--- a/libctf/ctf-impl.h
+++ b/libctf/ctf-impl.h
@@ -58,12 +58,41 @@ extern "C"
 
 #endif
 
+/* libctf in-memory state.  */
+
+typedef struct ctf_fixed_hash ctf_hash_t; /* Private to ctf-hash.c.  */
+typedef struct ctf_dynhash ctf_dynhash_t; /* Private to ctf-hash.c.  */
+
 typedef struct ctf_list
 {
   struct ctf_list *l_prev;	/* Previous pointer or tail pointer.  */
   struct ctf_list *l_next;	/* Next pointer or head pointer.  */
 } ctf_list_t;
 
+typedef unsigned int (*ctf_hash_fun) (const void *ptr);
+extern unsigned int ctf_hash_integer (const void *ptr);
+extern unsigned int ctf_hash_string (const void *ptr);
+
+typedef int (*ctf_hash_eq_fun) (const void *, const void *);
+extern int ctf_hash_eq_integer (const void *, const void *);
+extern int ctf_hash_eq_string (const void *, const void *);
+
+typedef void (*ctf_hash_free_fun) (void *);
+
+extern ctf_hash_t *ctf_hash_create (unsigned long, ctf_hash_fun, ctf_hash_eq_fun);
+extern int ctf_hash_insert_type (ctf_hash_t *, ctf_file_t *, uint32_t, uint32_t);
+extern int ctf_hash_define_type (ctf_hash_t *, ctf_file_t *, uint32_t, uint32_t);
+extern ctf_id_t ctf_hash_lookup_type (ctf_hash_t *, ctf_file_t *, const char *);
+extern uint32_t ctf_hash_size (const ctf_hash_t *);
+extern void ctf_hash_destroy (ctf_hash_t *);
+
+extern ctf_dynhash_t *ctf_dynhash_create (ctf_hash_fun, ctf_hash_eq_fun,
+					  ctf_hash_free_fun, ctf_hash_free_fun);
+extern int ctf_dynhash_insert (ctf_dynhash_t *, void *, void *);
+extern void ctf_dynhash_remove (ctf_dynhash_t *, const void *);
+extern void *ctf_dynhash_lookup (ctf_dynhash_t *, const void *);
+extern void ctf_dynhash_destroy (ctf_dynhash_t *);
+
 #define	ctf_list_prev(elem)	((void *)(((ctf_list_t *)(elem))->l_prev))
 #define	ctf_list_next(elem)	((void *)(((ctf_list_t *)(elem))->l_next))
 
-- 
2.21.0.237.gd0cfaa883d

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v2 13/19] libctf: type copying
  2019-05-17 22:10 [PATCH v2 00/19] libctf, and CTF support for objdump and readelf Nick Alcock
                   ` (11 preceding siblings ...)
  2019-05-17 22:10 ` [PATCH v2 04/19] libctf: low-level list manipulation and helper utilities Nick Alcock
@ 2019-05-17 22:10 ` Nick Alcock
  2019-05-17 22:10 ` [PATCH v2 09/19] libctf: opening Nick Alcock
                   ` (7 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nick Alcock @ 2019-05-17 22:10 UTC (permalink / raw)
  To: binutils

ctf_add_type() allows you to copy types, and all the types they depend
on, from one container to another (writable) container. This lets a
program maintaining multiple distinct containers (not in a parent-child
relationship) introduce types that depend on types in one container in
another writable one, by copying the necessary types.

Changes from v1:
 - Correct erroneous license (GPLv2+ -> v3+) and reset copyright years.
 - Adjust to ctf_free() prototype changes

libctf/
	* ctf-create.c (enumcmp): New.
	(enumadd): Likewise.
	(membcmp): Likewise.
	(membadd): Likewise.
	(ctf_add_type): Likewise.
---
 libctf/ctf-create.c | 485 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 485 insertions(+)

diff --git a/libctf/ctf-create.c b/libctf/ctf-create.c
index 42012d8342..f867da7776 100644
--- a/libctf/ctf-create.c
+++ b/libctf/ctf-create.c
@@ -1446,6 +1446,491 @@ ctf_add_variable (ctf_file_t *fp, const char *name, ctf_id_t ref)
   return 0;
 }
 
+static int
+enumcmp (const char *name, int value, void *arg)
+{
+  ctf_bundle_t *ctb = arg;
+  int bvalue;
+
+  if (ctf_enum_value (ctb->ctb_file, ctb->ctb_type, name, &bvalue) == CTF_ERR)
+    {
+      ctf_dprintf ("Conflict due to member %s iteration error.\n", name);
+      return 1;
+    }
+  if (value != bvalue)
+    {
+      ctf_dprintf ("Conflict due to value change: %i versus %i\n",
+		   value, bvalue);
+      return 1;
+    }
+  return 0;
+}
+
+static int
+enumadd (const char *name, int value, void *arg)
+{
+  ctf_bundle_t *ctb = arg;
+
+  return (ctf_add_enumerator (ctb->ctb_file, ctb->ctb_type,
+			      name, value) == CTF_ERR);
+}
+
+static int
+membcmp (const char *name, ctf_id_t type _libctf_unused_, unsigned long offset,
+	 void *arg)
+{
+  ctf_bundle_t *ctb = arg;
+  ctf_membinfo_t ctm;
+
+  if (ctf_member_info (ctb->ctb_file, ctb->ctb_type, name, &ctm) == CTF_ERR)
+    {
+      ctf_dprintf ("Conflict due to member %s iteration error.\n", name);
+      return 1;
+    }
+  if (ctm.ctm_offset != offset)
+    {
+      ctf_dprintf ("Conflict due to member %s offset change: "
+		   "%lx versus %lx\n", name, ctm.ctm_offset, offset);
+      return 1;
+    }
+  return 0;
+}
+
+static int
+membadd (const char *name, ctf_id_t type, unsigned long offset, void *arg)
+{
+  ctf_bundle_t *ctb = arg;
+  ctf_dmdef_t *dmd;
+  char *s = NULL;
+
+  if ((dmd = ctf_alloc (sizeof (ctf_dmdef_t))) == NULL)
+    return (ctf_set_errno (ctb->ctb_file, EAGAIN));
+
+  if (name != NULL && (s = ctf_strdup (name)) == NULL)
+    {
+      ctf_free (dmd);
+      return (ctf_set_errno (ctb->ctb_file, EAGAIN));
+    }
+
+  /* For now, dmd_type is copied as the src_fp's type; it is reset to an
+    equivalent dst_fp type by a final loop in ctf_add_type(), below.  */
+  dmd->dmd_name = s;
+  dmd->dmd_type = type;
+  dmd->dmd_offset = offset;
+  dmd->dmd_value = -1;
+
+  ctf_list_append (&ctb->ctb_dtd->dtd_u.dtu_members, dmd);
+
+  if (s != NULL)
+    ctb->ctb_file->ctf_dtvstrlen += strlen (s) + 1;
+
+  ctb->ctb_file->ctf_flags |= LCTF_DIRTY;
+  return 0;
+}
+
+/* The ctf_add_type routine is used to copy a type from a source CTF container
+   to a dynamic destination container.  This routine operates recursively by
+   following the source type's links and embedded member types.  If the
+   destination container already contains a named type which has the same
+   attributes, then we succeed and return this type but no changes occur.  */
+ctf_id_t
+ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
+{
+  ctf_id_t dst_type = CTF_ERR;
+  uint32_t dst_kind = CTF_K_UNKNOWN;
+  ctf_id_t tmp;
+
+  const char *name;
+  uint32_t kind, flag, vlen;
+
+  const ctf_type_t *src_tp, *dst_tp;
+  ctf_bundle_t src, dst;
+  ctf_encoding_t src_en, dst_en;
+  ctf_arinfo_t src_ar, dst_ar;
+
+  ctf_dtdef_t *dtd;
+  ctf_funcinfo_t ctc;
+  ssize_t size;
+
+  ctf_hash_t *hp;
+
+  if (!(dst_fp->ctf_flags & LCTF_RDWR))
+    return (ctf_set_errno (dst_fp, ECTF_RDONLY));
+
+  if ((src_tp = ctf_lookup_by_id (&src_fp, src_type)) == NULL)
+    return (ctf_set_errno (dst_fp, ctf_errno (src_fp)));
+
+  name = ctf_strptr (src_fp, src_tp->ctt_name);
+  kind = LCTF_INFO_KIND (src_fp, src_tp->ctt_info);
+  flag = LCTF_INFO_ISROOT (src_fp, src_tp->ctt_info);
+  vlen = LCTF_INFO_VLEN (src_fp, src_tp->ctt_info);
+
+  switch (kind)
+    {
+    case CTF_K_STRUCT:
+      hp = dst_fp->ctf_structs;
+      break;
+    case CTF_K_UNION:
+      hp = dst_fp->ctf_unions;
+      break;
+    case CTF_K_ENUM:
+      hp = dst_fp->ctf_enums;
+      break;
+    default:
+      hp = dst_fp->ctf_names;
+      break;
+    }
+
+  /* If the source type has a name and is a root type (visible at the
+     top-level scope), lookup the name in the destination container and
+     verify that it is of the same kind before we do anything else.  */
+
+  if ((flag & CTF_ADD_ROOT) && name[0] != '\0'
+      && (tmp = ctf_hash_lookup_type (hp, dst_fp, name)) != 0)
+    {
+      dst_type = tmp;
+      dst_kind = ctf_type_kind_unsliced (dst_fp, dst_type);
+    }
+
+  /* If an identically named dst_type exists, fail with ECTF_CONFLICT
+     unless dst_type is a forward declaration and src_type is a struct,
+     union, or enum (i.e. the definition of the previous forward decl).  */
+
+  if (dst_type != CTF_ERR && dst_kind != kind
+      && (dst_kind != CTF_K_FORWARD
+	  || (kind != CTF_K_ENUM && kind != CTF_K_STRUCT
+	      && kind != CTF_K_UNION)))
+    {
+      ctf_dprintf ("Conflict for type %s: kinds differ, new: %i; "
+		   "old (ID %lx): %i\n", name, kind, dst_type, dst_kind);
+      return (ctf_set_errno (dst_fp, ECTF_CONFLICT));
+    }
+
+  /* We take special action for an integer, float, or slice since it is
+     described not only by its name but also its encoding.  For integers,
+     bit-fields exploit this degeneracy.  */
+
+  if (kind == CTF_K_INTEGER || kind == CTF_K_FLOAT || kind == CTF_K_SLICE)
+    {
+      if (ctf_type_encoding (src_fp, src_type, &src_en) != 0)
+	return (ctf_set_errno (dst_fp, ctf_errno (src_fp)));
+
+      if (dst_type != CTF_ERR)
+	{
+	  ctf_file_t *fp = dst_fp;
+
+	  if ((dst_tp = ctf_lookup_by_id (&fp, dst_type)) == NULL)
+	    return CTF_ERR;
+
+	  if (LCTF_INFO_ISROOT (fp, dst_tp->ctt_info) & CTF_ADD_ROOT)
+	    {
+	      /* The type that we found in the hash is also root-visible.  If
+		 the two types match then use the existing one; otherwise,
+		 declare a conflict.  Note: slices are not certain to match
+		 even if there is no conflict: we must check the contained type
+		 too.  */
+
+	      if (ctf_type_encoding (dst_fp, dst_type, &dst_en) != 0)
+		return CTF_ERR;			/* errno set for us.  */
+
+	      if (memcmp (&src_en, &dst_en, sizeof (ctf_encoding_t)) == 0)
+		{
+		  if (kind != CTF_K_SLICE)
+		    return dst_type;
+		}
+	      else
+		  {
+		    return (ctf_set_errno (dst_fp, ECTF_CONFLICT));
+		  }
+	    }
+	  else
+	    {
+	      /* We found a non-root-visible type in the hash.  We reset
+	         dst_type to ensure that we continue to look for a possible
+	         conflict in the pending list.  */
+
+	      dst_type = CTF_ERR;
+	    }
+	}
+    }
+
+  /* If the non-empty name was not found in the appropriate hash, search
+     the list of pending dynamic definitions that are not yet committed.
+     If a matching name and kind are found, assume this is the type that
+     we are looking for.  This is necessary to permit ctf_add_type() to
+     operate recursively on entities such as a struct that contains a
+     pointer member that refers to the same struct type.  */
+
+  if (dst_type == CTF_ERR && name[0] != '\0')
+    {
+      for (dtd = ctf_list_prev (&dst_fp->ctf_dtdefs); dtd != NULL
+	     && LCTF_TYPE_TO_INDEX (src_fp, dtd->dtd_type) > dst_fp->ctf_dtoldid;
+	   dtd = ctf_list_prev (dtd))
+	{
+	  if (LCTF_INFO_KIND (src_fp, dtd->dtd_data.ctt_info) == kind
+	      && dtd->dtd_name != NULL && strcmp (dtd->dtd_name, name) == 0)
+	    {
+	      int sroot;	/* Is the src root-visible?  */
+	      int droot;	/* Is the dst root-visible?  */
+	      int match;	/* Do the encodings match?  */
+
+	      if (kind != CTF_K_INTEGER && kind != CTF_K_FLOAT && kind != CTF_K_SLICE)
+		return dtd->dtd_type;
+
+	      sroot = (flag & CTF_ADD_ROOT);
+	      droot = (LCTF_INFO_ISROOT (dst_fp,
+					 dtd->dtd_data.
+					 ctt_info) & CTF_ADD_ROOT);
+
+	      match = (memcmp (&src_en, &dtd->dtd_u.dtu_enc,
+			       sizeof (ctf_encoding_t)) == 0);
+
+	      /* If the types share the same encoding then return the id of the
+		 first unless one type is root-visible and the other is not; in
+		 that case the new type must get a new id if a match is never
+		 found.  Note: slices are not certain to match even if there is
+		 no conflict: we must check the contained type too. */
+
+	      if (match && sroot == droot)
+		{
+		  if (kind != CTF_K_SLICE)
+		    return dtd->dtd_type;
+		}
+	      else if (!match && sroot && droot)
+		{
+		  return (ctf_set_errno (dst_fp, ECTF_CONFLICT));
+		}
+	    }
+	}
+    }
+
+  src.ctb_file = src_fp;
+  src.ctb_type = src_type;
+  src.ctb_dtd = NULL;
+
+  dst.ctb_file = dst_fp;
+  dst.ctb_type = dst_type;
+  dst.ctb_dtd = NULL;
+
+  /* Now perform kind-specific processing.  If dst_type is CTF_ERR, then
+     we add a new type with the same properties as src_type to dst_fp.
+     If dst_type is not CTF_ERR, then we verify that dst_type has the
+     same attributes as src_type.  We recurse for embedded references.  */
+  switch (kind)
+    {
+    case CTF_K_INTEGER:
+      /*  If we found a match we will have either returned it or declared a
+	  conflict.  */
+      dst_type = ctf_add_integer (dst_fp, flag, name, &src_en);
+      break;
+
+    case CTF_K_FLOAT:
+      /* If we found a match we will have either returned it or declared a
+       conflict.  */
+      dst_type = ctf_add_float (dst_fp, flag, name, &src_en);
+      break;
+
+    case CTF_K_SLICE:
+      /* We have checked for conflicting encodings: now try to add the
+	 contained type.  */
+      src_type = ctf_type_reference (src_fp, src_type);
+      dst_type = ctf_add_type (dst_fp, src_fp, src_type);
+
+      if (src_type == CTF_ERR)
+	return CTF_ERR;				/* errno is set for us.  */
+
+      dst_type = ctf_add_slice (dst_fp, flag, src_type, &src_en);
+      break;
+
+    case CTF_K_POINTER:
+    case CTF_K_VOLATILE:
+    case CTF_K_CONST:
+    case CTF_K_RESTRICT:
+      src_type = ctf_type_reference (src_fp, src_type);
+      src_type = ctf_add_type (dst_fp, src_fp, src_type);
+
+      if (src_type == CTF_ERR)
+	return CTF_ERR;				/* errno is set for us.  */
+
+      dst_type = ctf_add_reftype (dst_fp, flag, src_type, kind);
+      break;
+
+    case CTF_K_ARRAY:
+      if (ctf_array_info (src_fp, src_type, &src_ar) == CTF_ERR)
+	return (ctf_set_errno (dst_fp, ctf_errno (src_fp)));
+
+      src_ar.ctr_contents =
+	ctf_add_type (dst_fp, src_fp, src_ar.ctr_contents);
+      src_ar.ctr_index = ctf_add_type (dst_fp, src_fp, src_ar.ctr_index);
+      src_ar.ctr_nelems = src_ar.ctr_nelems;
+
+      if (src_ar.ctr_contents == CTF_ERR || src_ar.ctr_index == CTF_ERR)
+	return CTF_ERR;				/* errno is set for us.  */
+
+      if (dst_type != CTF_ERR)
+	{
+	  if (ctf_array_info (dst_fp, dst_type, &dst_ar) != 0)
+	    return CTF_ERR;			/* errno is set for us.  */
+
+	  if (memcmp (&src_ar, &dst_ar, sizeof (ctf_arinfo_t)))
+	    {
+	      ctf_dprintf ("Conflict for type %s against ID %lx: "
+			   "array info differs, old %lx/%lx/%x; "
+			   "new: %lx/%lx/%x\n", name, dst_type,
+			   src_ar.ctr_contents, src_ar.ctr_index,
+			   src_ar.ctr_nelems, dst_ar.ctr_contents,
+			   dst_ar.ctr_index, dst_ar.ctr_nelems);
+	      return (ctf_set_errno (dst_fp, ECTF_CONFLICT));
+	    }
+	}
+      else
+	dst_type = ctf_add_array (dst_fp, flag, &src_ar);
+      break;
+
+    case CTF_K_FUNCTION:
+      ctc.ctc_return = ctf_add_type (dst_fp, src_fp, src_tp->ctt_type);
+      ctc.ctc_argc = 0;
+      ctc.ctc_flags = 0;
+
+      if (ctc.ctc_return == CTF_ERR)
+	return CTF_ERR;				/* errno is set for us.  */
+
+      dst_type = ctf_add_function (dst_fp, flag, &ctc, NULL);
+      break;
+
+    case CTF_K_STRUCT:
+    case CTF_K_UNION:
+      {
+	ctf_dmdef_t *dmd;
+	int errs = 0;
+
+	/* Technically to match a struct or union we need to check both
+	   ways (src members vs. dst, dst members vs. src) but we make
+	   this more optimal by only checking src vs. dst and comparing
+	   the total size of the structure (which we must do anyway)
+	   which covers the possibility of dst members not in src.
+	   This optimization can be defeated for unions, but is so
+	   pathological as to render it irrelevant for our purposes.  */
+
+	if (dst_type != CTF_ERR && dst_kind != CTF_K_FORWARD)
+	  {
+	    if (ctf_type_size (src_fp, src_type) !=
+		ctf_type_size (dst_fp, dst_type))
+	      {
+		ctf_dprintf ("Conflict for type %s against ID %lx: "
+			     "union size differs, old %li, new %li\n",
+			     name, dst_type, ctf_type_size (src_fp, src_type),
+			     ctf_type_size (dst_fp, dst_type));
+		return (ctf_set_errno (dst_fp, ECTF_CONFLICT));
+	      }
+
+	    if (ctf_member_iter (src_fp, src_type, membcmp, &dst))
+	      {
+		ctf_dprintf ("Conflict for type %s against ID %lx: "
+			     "members differ, see above\n", name, dst_type);
+		return (ctf_set_errno (dst_fp, ECTF_CONFLICT));
+	      }
+
+	    break;
+	  }
+
+	/* Unlike the other cases, copying structs and unions is done
+	   manually so as to avoid repeated lookups in ctf_add_member
+	   and to ensure the exact same member offsets as in src_type.  */
+
+	dst_type = ctf_add_generic (dst_fp, flag, name, &dtd);
+	if (dst_type == CTF_ERR)
+	  return CTF_ERR;			/* errno is set for us.  */
+
+	dst.ctb_type = dst_type;
+	dst.ctb_dtd = dtd;
+
+	if (ctf_member_iter (src_fp, src_type, membadd, &dst) != 0)
+	  errs++;	       /* Increment errs and fail at bottom of case.  */
+
+	if ((size = ctf_type_size (src_fp, src_type)) > CTF_MAX_SIZE)
+	  {
+	    dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
+	    dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (size);
+	    dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO (size);
+	  }
+	else
+	  dtd->dtd_data.ctt_size = (uint32_t) size;
+
+	dtd->dtd_data.ctt_info = CTF_TYPE_INFO (kind, flag, vlen);
+
+	/* Make a final pass through the members changing each dmd_type (a
+	   src_fp type) to an equivalent type in dst_fp.  We pass through all
+	   members, leaving any that fail set to CTF_ERR.  */
+	for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
+	     dmd != NULL; dmd = ctf_list_next (dmd))
+	  {
+	    if ((dmd->dmd_type = ctf_add_type (dst_fp, src_fp,
+					       dmd->dmd_type)) == CTF_ERR)
+	      errs++;
+	  }
+
+	if (errs)
+	  return CTF_ERR;			/* errno is set for us.  */
+	break;
+      }
+
+    case CTF_K_ENUM:
+      if (dst_type != CTF_ERR && dst_kind != CTF_K_FORWARD)
+	{
+	  if (ctf_enum_iter (src_fp, src_type, enumcmp, &dst)
+	      || ctf_enum_iter (dst_fp, dst_type, enumcmp, &src))
+	    {
+	      ctf_dprintf ("Conflict for enum %s against ID %lx: "
+			   "members differ, see above\n", name, dst_type);
+	      return (ctf_set_errno (dst_fp, ECTF_CONFLICT));
+	    }
+	}
+      else
+	{
+	  dst_type = ctf_add_enum (dst_fp, flag, name);
+	  if ((dst.ctb_type = dst_type) == CTF_ERR
+	      || ctf_enum_iter (src_fp, src_type, enumadd, &dst))
+	    return CTF_ERR;			/* errno is set for us */
+	}
+      break;
+
+    case CTF_K_FORWARD:
+      if (dst_type == CTF_ERR)
+	{
+	  dst_type = ctf_add_forward (dst_fp, flag,
+				      name, CTF_K_STRUCT); /* Assume STRUCT. */
+	}
+      break;
+
+    case CTF_K_TYPEDEF:
+      src_type = ctf_type_reference (src_fp, src_type);
+      src_type = ctf_add_type (dst_fp, src_fp, src_type);
+
+      if (src_type == CTF_ERR)
+	return CTF_ERR;				/* errno is set for us.  */
+
+      /* If dst_type is not CTF_ERR at this point, we should check if
+	 ctf_type_reference(dst_fp, dst_type) != src_type and if so fail with
+	 ECTF_CONFLICT.  However, this causes problems with bitness typedefs
+	 that vary based on things like if 32-bit then pid_t is int otherwise
+	 long.  We therefore omit this check and assume that if the identically
+	 named typedef already exists in dst_fp, it is correct or
+	 equivalent.  */
+
+      if (dst_type == CTF_ERR)
+	{
+	  dst_type = ctf_add_typedef (dst_fp, flag, name, src_type);
+	}
+      break;
+
+    default:
+      return (ctf_set_errno (dst_fp, ECTF_CORRUPT));
+    }
+
+  return dst_type;
+}
+
 /* Write the compressed CTF data stream to the specified gzFile descriptor.
    This is useful for saving the results of dynamic CTF containers.  */
 int
-- 
2.21.0.237.gd0cfaa883d

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v2 12/19] libctf: lookups by name and symbol
  2019-05-17 22:10 [PATCH v2 00/19] libctf, and CTF support for objdump and readelf Nick Alcock
@ 2019-05-17 22:10 ` Nick Alcock
  2019-05-17 22:10 ` [PATCH v2 05/19] libctf: error handling Nick Alcock
                   ` (19 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nick Alcock @ 2019-05-17 22:10 UTC (permalink / raw)
  To: binutils

These functions allow you to look up types given a name in a simple
subset of C declarator syntax (no function pointers), to look up the
types of variables given a name, and to look up the types of data
objects and the type signatures of functions given symbol table offsets.

(Despite its name, one function in this commit, ctf_lookup_symbol_name(),
is for the internal use of libctf only, and does not appear in any
public header files.)

Changes from v1:
 - Correct erroneous license (GPLv2+ -> v3+) and reset copyright years.
 - Move ctf_lookup_symbol_name() declaration from an earlier commit in
   the series.
 - Migrate from <gelf.h> to libctf-internal <elf.h>: we still look up
   symbols by hand, though, because we have to be able to look up
   symbols when the caller of ctf_bufopen() passes us raw symtabs and
   strtabs in buffers

libctf/
	* ctf-lookup.c (isqualifier): New.
	(ctf_lookup_by_name): Likewise.
	(struct ctf_lookup_var_key): Likewise.
	(ctf_lookup_var): Likewise.
	(ctf_lookup_variable): Likewise.
	(ctf_lookup_symbol_name): Likewise.
	(ctf_lookup_by_symbol): Likewise.
	(ctf_func_info): Likewise.
	(ctf_func_args): Likewise.

include/
	* ctf-api.h (ctf_func_info): New.
	(ctf_func_args): Likewise.
	(ctf_lookup_by_symbol): Likewise.
	(ctf_lookup_by_symbol): Likewise.
	(ctf_lookup_variable): Likewise.
---
 include/ctf-api.h   |   8 +
 libctf/ctf-impl.h   |   1 +
 libctf/ctf-lookup.c | 364 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 373 insertions(+)

diff --git a/include/ctf-api.h b/include/ctf-api.h
index 4dffa42565..049062ea80 100644
--- a/include/ctf-api.h
+++ b/include/ctf-api.h
@@ -239,6 +239,14 @@ extern void *ctf_getspecific (ctf_file_t *);
 
 extern int ctf_errno (ctf_file_t *);
 extern const char *ctf_errmsg (int);
+
+extern int ctf_func_info (ctf_file_t *, unsigned long, ctf_funcinfo_t *);
+extern int ctf_func_args (ctf_file_t *, unsigned long, uint32_t, ctf_id_t *);
+
+extern ctf_id_t ctf_lookup_by_name (ctf_file_t *, const char *);
+extern ctf_id_t ctf_lookup_by_symbol (ctf_file_t *, unsigned long);
+extern ctf_id_t ctf_lookup_variable (ctf_file_t *, const char *);
+
 extern ctf_id_t ctf_type_resolve (ctf_file_t *, ctf_id_t);
 extern char *ctf_type_aname (ctf_file_t *, ctf_id_t);
 extern ssize_t ctf_type_lname (ctf_file_t *, ctf_id_t, char *, size_t);
diff --git a/libctf/ctf-impl.h b/libctf/ctf-impl.h
index 80ce2c1c5b..91c46d5d5a 100644
--- a/libctf/ctf-impl.h
+++ b/libctf/ctf-impl.h
@@ -357,6 +357,7 @@ extern void ctf_dprintf (const char *, ...);
 extern void libctf_init_debug (void);
 
 extern Elf64_Sym *ctf_sym_to_elf64 (const Elf32_Sym *src, Elf64_Sym *dst);
+extern const char *ctf_lookup_symbol_name (ctf_file_t *fp, unsigned long symidx);
 
 /* Variables, all underscore-prepended. */
 
diff --git a/libctf/ctf-lookup.c b/libctf/ctf-lookup.c
index e76afb6e0a..7ea46a7295 100644
--- a/libctf/ctf-lookup.c
+++ b/libctf/ctf-lookup.c
@@ -21,6 +21,290 @@
 #include <elf.h>
 #include <string.h>
 
+/* Compare the given input string and length against a table of known C storage
+   qualifier keywords.  We just ignore these in ctf_lookup_by_name, below.  To
+   do this quickly, we use a pre-computed Perfect Hash Function similar to the
+   technique originally described in the classic paper:
+
+   R.J. Cichelli, "Minimal Perfect Hash Functions Made Simple",
+   Communications of the ACM, Volume 23, Issue 1, January 1980, pp. 17-19.
+
+   For an input string S of length N, we use hash H = S[N - 1] + N - 105, which
+   for the current set of qualifiers yields a unique H in the range [0 .. 20].
+   The hash can be modified when the keyword set changes as necessary.  We also
+   store the length of each keyword and check it prior to the final strcmp().
+
+   TODO: just use gperf.  */
+
+static int
+isqualifier (const char *s, size_t len)
+{
+  static const struct qual
+  {
+    const char *q_name;
+    size_t q_len;
+  } qhash[] = {
+    {"static", 6}, {"", 0}, {"", 0}, {"", 0},
+    {"volatile", 8}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
+    {"", 0}, {"auto", 4}, {"extern", 6}, {"", 0}, {"", 0},
+    {"", 0}, {"", 0}, {"const", 5}, {"register", 8},
+    {"", 0}, {"restrict", 8}, {"_Restrict", 9}
+  };
+
+  int h = s[len - 1] + (int) len - 105;
+  const struct qual *qp = &qhash[h];
+
+  return (h >= 0 && (size_t) h < sizeof (qhash) / sizeof (qhash[0])
+	  && (size_t) len == qp->q_len &&
+	  strncmp (qp->q_name, s, qp->q_len) == 0);
+}
+
+/* Attempt to convert the given C type name into the corresponding CTF type ID.
+   It is not possible to do complete and proper conversion of type names
+   without implementing a more full-fledged parser, which is necessary to
+   handle things like types that are function pointers to functions that
+   have arguments that are function pointers, and fun stuff like that.
+   Instead, this function implements a very simple conversion algorithm that
+   finds the things that we actually care about: structs, unions, enums,
+   integers, floats, typedefs, and pointers to any of these named types.  */
+
+ctf_id_t
+ctf_lookup_by_name (ctf_file_t *fp, const char *name)
+{
+  static const char delimiters[] = " \t\n\r\v\f*";
+
+  const ctf_lookup_t *lp;
+  const char *p, *q, *end;
+  ctf_id_t type = 0;
+  ctf_id_t ntype, ptype;
+
+  if (name == NULL)
+    return (ctf_set_errno (fp, EINVAL));
+
+  for (p = name, end = name + strlen (name); *p != '\0'; p = q)
+    {
+      while (isspace (*p))
+	p++;			/* Skip leading whitespace.  */
+
+      if (p == end)
+	break;
+
+      if ((q = strpbrk (p + 1, delimiters)) == NULL)
+	q = end;		/* Compare until end.  */
+
+      if (*p == '*')
+	{
+	  /* Find a pointer to type by looking in fp->ctf_ptrtab.
+	     If we can't find a pointer to the given type, see if
+	     we can compute a pointer to the type resulting from
+	     resolving the type down to its base type and use
+	     that instead.  This helps with cases where the CTF
+	     data includes "struct foo *" but not "foo_t *" and
+	     the user tries to access "foo_t *" in the debugger.
+
+	     TODO need to handle parent containers too.  */
+
+	  ntype = fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX (fp, type)];
+	  if (ntype == 0)
+	    {
+	      ntype = ctf_type_resolve_unsliced (fp, type);
+	      if (ntype == CTF_ERR
+		  || (ntype =
+		      fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX (fp, ntype)]) == 0)
+		{
+		  (void) ctf_set_errno (fp, ECTF_NOTYPE);
+		  goto err;
+		}
+	    }
+
+	  type = LCTF_INDEX_TO_TYPE (fp, ntype, (fp->ctf_flags & LCTF_CHILD));
+
+	  q = p + 1;
+	  continue;
+	}
+
+      if (isqualifier (p, (size_t) (q - p)))
+	continue;		/* Skip qualifier keyword.  */
+
+      for (lp = fp->ctf_lookups; lp->ctl_prefix != NULL; lp++)
+	{
+	  /* TODO: This is not MT-safe.  */
+	  if ((lp->ctl_prefix[0] == '\0' ||
+	       strncmp (p, lp->ctl_prefix, (size_t) (q - p)) == 0) &&
+	      (size_t) (q - p) >= lp->ctl_len)
+	    {
+	      for (p += lp->ctl_len; isspace (*p); p++)
+		continue;	/* Skip prefix and next whitespace.  */
+
+	      if ((q = strchr (p, '*')) == NULL)
+		q = end;	/* Compare until end.  */
+
+	      while (isspace (q[-1]))
+		q--;		/* Exclude trailing whitespace.  */
+
+	      /* Expand and/or allocate storage for a slice of the name, then
+		 copy it in.  */
+
+	      if (fp->ctf_tmp_typeslicelen >= (size_t) (q - p) + 1)
+		{
+		  memcpy (fp->ctf_tmp_typeslice, p, (size_t) (q - p));
+		  fp->ctf_tmp_typeslice[(size_t) (q - p)] = '\0';
+		}
+	      else
+		{
+		  free (fp->ctf_tmp_typeslice);
+		  fp->ctf_tmp_typeslice = strndup (p, (size_t) (q - p));
+		  if (fp->ctf_tmp_typeslice == NULL)
+		    {
+		      (void) ctf_set_errno (fp, ENOMEM);
+		      return CTF_ERR;
+		    }
+		}
+
+	      if ((type = ctf_hash_lookup_type (lp->ctl_hash, fp,
+						fp->ctf_tmp_typeslice)) == 0)
+		{
+		  (void) ctf_set_errno (fp, ECTF_NOTYPE);
+		  goto err;
+		}
+
+	      break;
+	    }
+	}
+
+      if (lp->ctl_prefix == NULL)
+	{
+	  (void) ctf_set_errno (fp, ECTF_NOTYPE);
+	  goto err;
+	}
+    }
+
+  if (*p != '\0' || type == 0)
+    return (ctf_set_errno (fp, ECTF_SYNTAX));
+
+  return type;
+
+err:
+  if (fp->ctf_parent != NULL
+      && (ptype = ctf_lookup_by_name (fp->ctf_parent, name)) != CTF_ERR)
+    return ptype;
+
+  return CTF_ERR;
+}
+
+typedef struct ctf_lookup_var_key
+{
+  ctf_file_t *clvk_fp;
+  const char *clvk_name;
+} ctf_lookup_var_key_t;
+
+/* A bsearch function for variable names.  */
+
+static int
+ctf_lookup_var (const void *key_, const void *memb_)
+{
+  const ctf_lookup_var_key_t *key = key_;
+  const ctf_varent_t *memb = memb_;
+
+  return (strcmp (key->clvk_name, ctf_strptr (key->clvk_fp, memb->ctv_name)));
+}
+
+/* Given a variable name, return the type of the variable with that name.  */
+
+ctf_id_t
+ctf_lookup_variable (ctf_file_t *fp, const char *name)
+{
+  ctf_varent_t *ent;
+  ctf_lookup_var_key_t key = { fp, name };
+
+  /* This array is sorted, so we can bsearch for it.  */
+
+  ent = bsearch (&key, fp->ctf_vars, fp->ctf_nvars, sizeof (ctf_varent_t),
+		 ctf_lookup_var);
+
+  if (ent == NULL)
+    {
+      if (fp->ctf_parent != NULL)
+	return ctf_lookup_variable (fp->ctf_parent, name);
+
+      return (ctf_set_errno (fp, ECTF_NOTYPEDAT));
+    }
+
+  return ent->ctv_type;
+}
+
+/* Given a symbol table index, return the name of that symbol from the secondary
+   string table, or the null string (never NULL).  */
+const char *
+ctf_lookup_symbol_name (ctf_file_t *fp, unsigned long symidx)
+{
+  const ctf_sect_t *sp = &fp->ctf_symtab;
+  Elf64_Sym sym, *gsp;
+
+  if (sp->cts_data == NULL)
+    {
+      ctf_set_errno (fp, ECTF_NOSYMTAB);
+      return _CTF_NULLSTR;
+    }
+
+  if (symidx >= fp->ctf_nsyms)
+    {
+      ctf_set_errno (fp, EINVAL);
+      return _CTF_NULLSTR;
+    }
+
+  if (sp->cts_entsize == sizeof (Elf32_Sym))
+    {
+      const Elf32_Sym *symp = (Elf32_Sym *) sp->cts_data + symidx;
+      gsp = ctf_sym_to_elf64 (symp, &sym);
+    }
+  else
+      gsp = (Elf64_Sym *) sp->cts_data + symidx;
+
+  if (gsp->st_name < fp->ctf_str[CTF_STRTAB_1].cts_len)
+    return (const char *) fp->ctf_str[CTF_STRTAB_1].cts_strs + gsp->st_name;
+
+  return _CTF_NULLSTR;
+}
+
+/* Given a symbol table index, return the type of the data object described
+   by the corresponding entry in the symbol table.  */
+
+ctf_id_t
+ctf_lookup_by_symbol (ctf_file_t *fp, unsigned long symidx)
+{
+  const ctf_sect_t *sp = &fp->ctf_symtab;
+  ctf_id_t type;
+
+  if (sp->cts_data == NULL)
+    return (ctf_set_errno (fp, ECTF_NOSYMTAB));
+
+  if (symidx >= fp->ctf_nsyms)
+    return (ctf_set_errno (fp, EINVAL));
+
+  if (sp->cts_entsize == sizeof (Elf32_Sym))
+    {
+      const Elf32_Sym *symp = (Elf32_Sym *) sp->cts_data + symidx;
+      if (ELF32_ST_TYPE (symp->st_info) != STT_OBJECT)
+	return (ctf_set_errno (fp, ECTF_NOTDATA));
+    }
+  else
+    {
+      const Elf64_Sym *symp = (Elf64_Sym *) sp->cts_data + symidx;
+      if (ELF64_ST_TYPE (symp->st_info) != STT_OBJECT)
+	return (ctf_set_errno (fp, ECTF_NOTDATA));
+    }
+
+  if (fp->ctf_sxlate[symidx] == -1u)
+    return (ctf_set_errno (fp, ECTF_NOTYPEDAT));
+
+  type = *(uint32_t *) ((uintptr_t) fp->ctf_buf + fp->ctf_sxlate[symidx]);
+  if (type == 0)
+    return (ctf_set_errno (fp, ECTF_NOTYPEDAT));
+
+  return type;
+}
+
 /* Return the pointer to the internal CTF type data corresponding to the
    given type ID.  If the ID is invalid, the function returns NULL.
    This function is not exported outside of the library.  */
@@ -61,3 +345,83 @@ ctf_lookup_by_id (ctf_file_t **fpp, ctf_id_t type)
   return NULL;
 }
 
+/* Given a symbol table index, return the info for the function described
+   by the corresponding entry in the symbol table.  */
+
+int
+ctf_func_info (ctf_file_t *fp, unsigned long symidx, ctf_funcinfo_t *fip)
+{
+  const ctf_sect_t *sp = &fp->ctf_symtab;
+  const uint32_t *dp;
+  uint32_t info, kind, n;
+
+  if (sp->cts_data == NULL)
+    return (ctf_set_errno (fp, ECTF_NOSYMTAB));
+
+  if (symidx >= fp->ctf_nsyms)
+    return (ctf_set_errno (fp, EINVAL));
+
+  if (sp->cts_entsize == sizeof (Elf32_Sym))
+    {
+      const Elf32_Sym *symp = (Elf32_Sym *) sp->cts_data + symidx;
+      if (ELF32_ST_TYPE (symp->st_info) != STT_FUNC)
+	return (ctf_set_errno (fp, ECTF_NOTFUNC));
+    }
+  else
+    {
+      const Elf64_Sym *symp = (Elf64_Sym *) sp->cts_data + symidx;
+      if (ELF64_ST_TYPE (symp->st_info) != STT_FUNC)
+	return (ctf_set_errno (fp, ECTF_NOTFUNC));
+    }
+
+  if (fp->ctf_sxlate[symidx] == -1u)
+    return (ctf_set_errno (fp, ECTF_NOFUNCDAT));
+
+  dp = (uint32_t *) ((uintptr_t) fp->ctf_buf + fp->ctf_sxlate[symidx]);
+
+  info = *dp++;
+  kind = LCTF_INFO_KIND (fp, info);
+  n = LCTF_INFO_VLEN (fp, info);
+
+  if (kind == CTF_K_UNKNOWN && n == 0)
+    return (ctf_set_errno (fp, ECTF_NOFUNCDAT));
+
+  if (kind != CTF_K_FUNCTION)
+    return (ctf_set_errno (fp, ECTF_CORRUPT));
+
+  fip->ctc_return = *dp++;
+  fip->ctc_argc = n;
+  fip->ctc_flags = 0;
+
+  if (n != 0 && dp[n - 1] == 0)
+    {
+      fip->ctc_flags |= CTF_FUNC_VARARG;
+      fip->ctc_argc--;
+    }
+
+  return 0;
+}
+
+/* Given a symbol table index, return the arguments for the function described
+   by the corresponding entry in the symbol table.  */
+
+int
+ctf_func_args (ctf_file_t * fp, unsigned long symidx, uint32_t argc,
+	       ctf_id_t * argv)
+{
+  const uint32_t *dp;
+  ctf_funcinfo_t f;
+
+  if (ctf_func_info (fp, symidx, &f) == CTF_ERR)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  /* The argument data is two uint32_t's past the translation table
+     offset: one for the function info, and one for the return type. */
+
+  dp = (uint32_t *) ((uintptr_t) fp->ctf_buf + fp->ctf_sxlate[symidx]) + 2;
+
+  for (argc = MIN (argc, f.ctc_argc); argc != 0; argc--)
+    *argv++ = *dp++;
+
+  return 0;
+}
-- 
2.21.0.237.gd0cfaa883d

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v2 03/19] libctf: lowest-level memory allocation and debug-dumping wrappers
  2019-05-17 22:10 [PATCH v2 00/19] libctf, and CTF support for objdump and readelf Nick Alcock
                   ` (4 preceding siblings ...)
  2019-05-17 22:10 ` [PATCH v2 07/19] libctf: implementation definitions related to file creation Nick Alcock
@ 2019-05-17 22:10 ` Nick Alcock
  2019-05-17 22:10 ` [PATCH v2 06/19] libctf: hashing Nick Alcock
                   ` (14 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nick Alcock @ 2019-05-17 22:10 UTC (permalink / raw)
  To: binutils

The memory-allocation wrappers are simple things to allow malloc
interposition: they are only used inconsistently at present, usually
where malloc debugging was required in the past.

These provide a default implementation that is environment-variable
triggered (initialized on the first call to the libctf creation and
file-opening functions, the first functions people will use), and
a ctf_setdebug()/ctf_getdebug() pair that allows the caller to
explicitly turn debugging off and on.  If ctf_setdebug() is called,
the automatic setting from an environment variable is skipped.

Changes from v1:
 - Correct erroneous license (GPLv2+ -> v3+) and reset copyright years.
 - Add ctf_getdebug, ctf_setdebug, libctf_init_debug (internal),
   ctf_mmap, ctf_munmap, ctf_pread, _libctf_malloc_
 - Remove _libctf_constructor_, libctf_destructor_
 - Mark a bunch of functions with _libctf_malloc_
 - Remove the size arg from ctf_free.
 - Remove ctf-lib and all therein: in this commit, its only user
   has migrated to ctf-subr.c and been renamed libctf_init_debug:
   it is no longer an ELF constructor.
 - Support platforms without mmap() or mprotect(), and platforms without
   pread().
 - Flush stdout when debug dumping.

libctf/
	* ctf-impl.h: New file.
	* ctf-subr.c: New file.

include/
	* ctf-api.h (ctf_setdebug): New.
	(ctf_getdebug): Likewise.
---
 include/ctf-api.h |   3 +
 libctf/ctf-impl.h |  78 ++++++++++++++++
 libctf/ctf-subr.c | 232 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 313 insertions(+)
 create mode 100644 libctf/ctf-impl.h
 create mode 100644 libctf/ctf-subr.c

diff --git a/include/ctf-api.h b/include/ctf-api.h
index f2f7ce1b43..aab85192ca 100644
--- a/include/ctf-api.h
+++ b/include/ctf-api.h
@@ -123,6 +123,9 @@ enum
 #define	CTF_ADD_ROOT	1	/* Type visible at top-level scope.  */
 
 
+extern void ctf_setdebug (int debug);
+extern int ctf_getdebug (void);
+
 #ifdef	__cplusplus
 }
 #endif
diff --git a/libctf/ctf-impl.h b/libctf/ctf-impl.h
new file mode 100644
index 0000000000..4356a2a9f0
--- /dev/null
+++ b/libctf/ctf-impl.h
@@ -0,0 +1,78 @@
+/* Implementation header.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+
+   This file is part of libctf.
+
+   libctf is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+   See the GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef	_CTF_IMPL_H
+#define	_CTF_IMPL_H
+
+#include "config.h"
+#include <sys/errno.h>
+#include <ctf-api.h>
+#include <sys/types.h>
+
+#ifdef	__cplusplus
+extern "C"
+  {
+#endif
+
+/* Compiler attributes.  */
+
+#if defined (__GNUC__)
+
+/* GCC.  We assume that all compilers claiming to be GCC support sufficiently
+   many GCC attributes that the code below works.  If some non-GCC compilers
+   masquerading as GCC in fact do not implement these attributes, version checks
+   may be required.  */
+
+/* We use the _libctf_*_ pattern to avoid clashes with any future attribute
+   macros glibc may introduce, which have names of the pattern
+   __attribute_blah__.  */
+
+#define _libctf_printflike_(string_index,first_to_check) \
+    __attribute__ ((__format__ (__printf__, (string_index), (first_to_check))))
+#define _libctf_unlikely_(x) __builtin_expect ((x), 0)
+#define _libctf_unused_ __attribute__ ((__unused__))
+#define _libctf_malloc_ __attribute__((__malloc__))
+
+#endif
+
+_libctf_malloc_
+extern void *ctf_data_alloc (size_t);
+extern void ctf_data_free (void *, size_t);
+extern void ctf_data_protect (void *, size_t);
+
+_libctf_malloc_
+extern void *ctf_mmap (size_t length, size_t offset, int fd);
+extern void ctf_munmap (void *, size_t);
+extern ssize_t ctf_pread (int fd, void *buf, ssize_t count, off_t offset);
+
+_libctf_malloc_
+extern void *ctf_alloc (size_t);
+extern void ctf_free (void *);
+
+_libctf_printflike_ (1, 2)
+extern void ctf_dprintf (const char *, ...);
+extern void libctf_init_debug (void);
+
+extern int _libctf_debug;	/* debugging messages enabled */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* _CTF_IMPL_H */
diff --git a/libctf/ctf-subr.c b/libctf/ctf-subr.c
new file mode 100644
index 0000000000..3103e28a3f
--- /dev/null
+++ b/libctf/ctf-subr.c
@@ -0,0 +1,232 @@
+/* Simple subrs.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+
+   This file is part of libctf.
+
+   libctf is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+   See the GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <ctf-impl.h>
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+#endif
+#include <sys/types.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+
+static size_t _PAGESIZE _libctf_unused_;
+int _libctf_debug = 0;			      /* Debugging messages enabled.  */
+
+_libctf_malloc_ void *
+ctf_data_alloc (size_t size)
+{
+  void *ret;
+
+#ifdef HAVE_MMAP
+  if (_PAGESIZE == 0)
+    _PAGESIZE = sysconf(_SC_PAGESIZE);
+
+  if (size > _PAGESIZE)
+    {
+      ret = mmap (NULL, size, PROT_READ | PROT_WRITE,
+		  MAP_PRIVATE | MAP_ANON, -1, 0);
+      if (ret == MAP_FAILED)
+	ret = NULL;
+    }
+  else
+    ret = calloc (1, size);
+#else
+  ret = calloc (1, size);
+#endif
+  return ret;
+}
+
+void
+ctf_data_free (void *buf, size_t size _libctf_unused_)
+{
+#ifdef HAVE_MMAP
+  /* Must be the same as the check in ctf_data_alloc().  */
+
+  if (size > _PAGESIZE)
+    (void) munmap (buf, size);
+  else
+    free (buf);
+#else
+  free (buf);
+#endif
+}
+
+/* Private, read-only mmap from a file, with fallback to copying.
+
+   No handling of page-offset issues at all: the caller must allow for that. */
+
+_libctf_malloc_ void *
+ctf_mmap (size_t length, size_t offset, int fd)
+{
+  void *data;
+
+#ifdef HAVE_MMAP
+  data = mmap (NULL, length, PROT_READ, MAP_PRIVATE, fd, offset);
+  if (data == MAP_FAILED)
+    data = NULL;
+#else
+  if ((data = malloc (length)) != NULL)
+    {
+      if (ctf_pread (fd, data, length, offset) <= 0)
+	{
+	  free (data);
+	  data = NULL;
+	}
+    }
+#endif
+  return data;
+}
+
+void
+ctf_munmap (void *buf, size_t length _libctf_unused_)
+{
+#ifdef HAVE_MMAP
+  (void) munmap (buf, length);
+#else
+  free (buf);
+#endif
+}
+
+void
+ctf_data_protect (void *buf, size_t size)
+{
+#ifdef HAVE_MMAP
+  /* Must be the same as the check in ctf_data_alloc().  */
+
+  if (size > _PAGESIZE)
+    (void) mprotect (buf, size, PROT_READ);
+#endif
+}
+
+_libctf_malloc_ void *
+ctf_alloc (size_t size)
+{
+  return (malloc (size));
+}
+
+void
+ctf_free (void *buf)
+{
+  free (buf);
+}
+
+ssize_t
+ctf_pread (int fd, void *buf, ssize_t count, off_t offset)
+{
+  ssize_t len;
+  size_t acc = 0;
+  char *data = (char *) buf;
+
+#ifdef HAVE_PREAD
+  while (count > 0)
+    {
+      errno = 0;
+      if (((len = pread (fd, data, count, offset)) < 0) &&
+	  errno != EINTR)
+	  return len;
+      if (errno == EINTR)
+	continue;
+
+      acc += len;
+      if (len == 0)				/* EOF.  */
+	return acc;
+
+      count -= len;
+      offset += len;
+      data += len;
+    }
+  return acc;
+#else
+  off_t orig_off;
+
+  if ((orig_off = lseek (fd, 0, SEEK_CUR)) < 0)
+    return -1;
+  if ((lseek (fd, offset, SEEK_SET)) < 0)
+    return -1;
+
+  while (count > 0)
+    {
+      errno = 0;
+      if (((len = read (fd, data, count)) < 0) &&
+	  errno != EINTR)
+	  return len;
+      if (errno == EINTR)
+	continue;
+
+      acc += len;
+      if (len == 0)				/* EOF.  */
+	break;
+
+      count -= len;
+      data += len;
+    }
+  if ((lseek (fd, orig_off, SEEK_SET)) < 0)
+    return -1;					/* offset is smashed.  */
+#endif
+
+  return acc;
+}
+
+const char *
+ctf_strerror (int err)
+{
+  return (const char *) (strerror (err));
+}
+
+void
+libctf_init_debug (void)
+{
+  static int inited;
+  if (!inited)
+    {
+      _libctf_debug = getenv ("LIBCTF_DEBUG") != NULL;
+      inited = 1;
+    }
+}
+
+void ctf_setdebug (int debug)
+{
+  /* Ensure that libctf_init_debug() has been called, so that we don't get our
+     debugging-on-or-off smashed by the next call.  */
+
+  libctf_init_debug();
+  _libctf_debug = debug;
+  ctf_dprintf ("CTF debugging set to %i\n", debug);
+}
+
+int ctf_getdebug (void)
+{
+  return _libctf_debug;
+}
+
+_libctf_printflike_ (1, 2)
+void ctf_dprintf (const char *format, ...)
+{
+  if (_libctf_debug)
+    {
+      va_list alist;
+
+      va_start (alist, format);
+      fflush (stdout);
+      (void) fputs ("libctf DEBUG: ", stderr);
+      (void) vfprintf (stderr, format, alist);
+      va_end (alist);
+    }
+}
-- 
2.21.0.237.gd0cfaa883d

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v2 15/19] libctf: mmappable archives
  2019-05-17 22:10 [PATCH v2 00/19] libctf, and CTF support for objdump and readelf Nick Alcock
                   ` (7 preceding siblings ...)
  2019-05-17 22:10 ` [PATCH v2 19/19] binutils: CTF support for objdump and readelf Nick Alcock
@ 2019-05-17 22:10 ` Nick Alcock
  2019-05-17 22:10 ` [PATCH v2 14/19] libctf: library version enforcement Nick Alcock
                   ` (11 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nick Alcock @ 2019-05-17 22:10 UTC (permalink / raw)
  To: binutils

If you need to store a large number of CTF containers somewhere, this
provides a dedicated facility for doing so: an mmappable archive format
like a very simple tar or ar without all the system-dependent format
horrors or need for heavy file copying, with built-in compression of
files above a particular size threshold.

libctf automatically mmap()s uncompressed elements of these archives, or
uncompresses them, as needed.  (If the platform does not support mmap(),
copying into dynamically-allocated buffers is used.)

Archive iteration operations are partitioned into raw and non-raw
forms. Raw operations pass thhe raw archive contents to the callback:
non-raw forms open each member with ctf_bufopen() and pass the resulting
ctf_file_t to the iterator instead.  This lets you manipulate the raw
data in the archive, or the contents interpreted as a CTF file, as
needed.

It is not yet known whether we will store CTF archives in a linked ELF
object in one of these (akin to debugdata) or whether they'll get one
section per TU plus one parent container for types shared between them.
(In the case of ELF objects with very large numbers of TUs, an archive
of all of them would seem preferable, so we might just use an archive,
and add lzma support so you can assume that .gnu_debugdata and .ctf are
compressed using the same algorithm if both are present.)

Changes from v1:
 - Correct erroneous license (GPLv2+ -> v3+) and reset copyright years.
 - Migrate the ctf_archive_t definition from ctf-impl.h into ctf.h: it
   is part of the file format, so it belongs there
 - Work on systems without mmap(), falling back to explicit I/O and
   dynamic memory allocation.

libctf/
	* ctf-archive.c: New.
include/
	* ctf.h (CTFA_MAGIC): New.
	(struct ctf_archive): New.
	(struct ctf_archive_modent): Likewise.
	* ctf-api.h (ctf_archive_member_f): New.
	(ctf_archive_raw_member_f): Likewise.
	(ctf_arc_write): Likewise.
	(ctf_arc_open): Likewise.
	(ctf_arc_close): Likewise.
	(ctf_arc_open_by_name): Likewise.
	(ctf_archive_iter): Likewise.
	(ctf_archive_raw_iter): Likewise.
---
 include/ctf-api.h    |  14 +
 include/ctf.h        |  44 +++
 libctf/ctf-archive.c | 617 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 675 insertions(+)
 create mode 100644 libctf/ctf-archive.c

diff --git a/include/ctf-api.h b/include/ctf-api.h
index 81f790dafd..6d6efdd513 100644
--- a/include/ctf-api.h
+++ b/include/ctf-api.h
@@ -213,6 +213,9 @@ typedef int ctf_member_f (const char *name, ctf_id_t membtype,
 typedef int ctf_enum_f (const char *name, int val, void *arg);
 typedef int ctf_variable_f (const char *name, ctf_id_t type, void *arg);
 typedef int ctf_type_f (ctf_id_t type, void *arg);
+typedef int ctf_archive_member_f (ctf_file_t *fp, const char *name, void *arg);
+typedef int ctf_archive_raw_member_f (const char *name, const void *content,
+				      size_t len, void *arg);
 extern ctf_file_t *ctf_simple_open (const char *, size_t, const char *, size_t,
 				   size_t, const char *, size_t, int *);
 extern ctf_file_t *ctf_bfdopen (struct bfd *, int *);
@@ -224,6 +227,13 @@ extern ctf_file_t *ctf_create (int *);
 extern void ctf_close (ctf_file_t *);
 extern ctf_sect_t ctf_getdatasect (const ctf_file_t *);
 
+extern int ctf_arc_write (const char *, ctf_file_t **, size_t,
+			  const char **, size_t);
+extern ctf_archive_t *ctf_arc_open (const char *, int *);
+extern void ctf_arc_close (ctf_archive_t *);
+extern ctf_file_t *ctf_arc_open_by_name (const ctf_archive_t *,
+					 const char *, int *);
+
 extern ctf_file_t *ctf_parent_file (ctf_file_t *);
 extern const char *ctf_parent_name (ctf_file_t *);
 extern void ctf_parent_name_set (ctf_file_t *, const char *);
@@ -273,6 +283,10 @@ extern int ctf_member_iter (ctf_file_t *, ctf_id_t, ctf_member_f *, void *);
 extern int ctf_enum_iter (ctf_file_t *, ctf_id_t, ctf_enum_f *, void *);
 extern int ctf_type_iter (ctf_file_t *, ctf_type_f *, void *);
 extern int ctf_variable_iter (ctf_file_t *, ctf_variable_f *, void *);
+extern int ctf_archive_iter (const ctf_archive_t *, ctf_archive_member_f *,
+			     void *);
+extern int ctf_archive_raw_iter (const ctf_archive_t *,
+				 ctf_archive_raw_member_f *, void *);
 extern ctf_id_t ctf_add_array (ctf_file_t *, uint32_t,
 			       const ctf_arinfo_t *);
 extern ctf_id_t ctf_add_const (ctf_file_t *, uint32_t, ctf_id_t);
diff --git a/include/ctf.h b/include/ctf.h
index 6580a2143c..2905fbec17 100644
--- a/include/ctf.h
+++ b/include/ctf.h
@@ -510,6 +510,50 @@ typedef struct ctf_enum
   int cte_value;		/* Value associated with this name.  */
 } ctf_enum_t;
 
+/* The ctf_archive is a collection of ctf_file_t's stored together. The format
+   is suitable for mmap()ing: this control structure merely describes the
+   mmap()ed archive (and overlaps the first few bytes of it), hence the
+   greater care taken with integral types.  All CTF files in an archive
+   must have the same data model.  (This is not validated.)
+
+   All integers in this structure are stored in little-endian byte order.
+
+   The code relies on the fact that everything in this header is a uint64_t
+   and thus the header needs no padding (in particular, that no padding is
+   needed between ctfa_ctfs and the unnamed ctfa_archive_modent array
+   that follows it).  */
+
+#define CTFA_MAGIC 0x8b47f2a4d7623eeb	/* Random.  */
+struct ctf_archive
+{
+  /* Magic number.  (In loaded files, overwritten with the file size
+     so ctf_arc_close() knows how much to munmap()).  */
+  uint64_t ctfa_magic;
+
+  /* CTF data model.  */
+  uint64_t ctfa_model;
+
+  /* Number of CTF files in the archive.  */
+  uint64_t ctfa_nfiles;
+
+  /* Offset of the name table.  */
+  uint64_t ctfa_names;
+
+  /* Offset of the CTF table.  Each element starts with a size (a uint64_t
+     in network byte order) then a ctf_file_t of that size.  */
+  uint64_t ctfa_ctfs;
+};
+
+/* An array of ctfa_nnamed of this structure lies at
+   ctf_archive[ctf_archive->ctfa_modents] and gives the ctfa_ctfs or
+   ctfa_names-relative offsets of each name or ctf_file_t.  */
+
+typedef struct ctf_archive_modent
+{
+  uint64_t name_offset;
+  uint64_t ctf_offset;
+} ctf_archive_modent_t;
+
 #ifdef	__cplusplus
 }
 #endif
diff --git a/libctf/ctf-archive.c b/libctf/ctf-archive.c
new file mode 100644
index 0000000000..5342c3582b
--- /dev/null
+++ b/libctf/ctf-archive.c
@@ -0,0 +1,617 @@
+/* CTF archive files.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+
+   This file is part of libctf.
+
+   libctf is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+   See the GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <ctf-impl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <elf.h>
+#include <endian.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+#endif
+
+static off_t arc_write_one_ctf (ctf_file_t * f, int fd, size_t threshold);
+static ctf_file_t *ctf_arc_open_by_offset (const ctf_archive_t * arc,
+					   size_t offset, int *errp);
+static int sort_modent_by_name (const void *one, const void *two, void *n);
+static void *arc_mmap_header (int fd, size_t headersz);
+static void *arc_mmap_file (int fd, size_t size);
+static int arc_mmap_writeout (int fd, void *header, size_t headersz,
+			      const char **errmsg);
+static int arc_mmap_unmap (void *header, size_t headersz, const char **errmsg);
+
+/* bsearch() internal state.  */
+static __thread char *search_nametbl;
+
+/* Write out a CTF archive.  The entries in CTF_FILES are referenced by name:
+   the names are passed in the names array, which must have CTF_FILES entries.
+
+   Returns 0 on success, or an errno, or an ECTF_* value.  */
+int
+ctf_arc_write (const char *file, ctf_file_t ** ctf_files, size_t ctf_file_cnt,
+	       const char **names, size_t threshold)
+{
+  const char *errmsg;
+  struct ctf_archive *archdr;
+  int fd;
+  size_t i;
+  char dummy = 0;
+  size_t headersz;
+  ssize_t namesz;
+  size_t ctf_startoffs;		/* Start of the section we are working over.  */
+  char *nametbl = NULL;		/* The name table.  */
+  char *np;
+  off_t nameoffs;
+  struct ctf_archive_modent *modent;
+
+  ctf_dprintf ("Writing archive %s with %zi files\n", file, ctf_file_cnt);
+
+  if ((fd = open (file, O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0666)) < 0)
+    {
+      errmsg = "ctf_arc_write(): cannot create %s: %s\n";
+      goto err;
+    }
+
+  /* Figure out the size of the mmap()ed header, including the
+     ctf_archive_modent array.  We assume that all of this needs no
+     padding: a likely assumption, given that it's all made up of
+     uint64_t's.  */
+  headersz = sizeof (struct ctf_archive)
+    + (ctf_file_cnt * sizeof (uint64_t) * 2);
+  ctf_dprintf ("headersz is %zi\n", headersz);
+
+  /* From now on we work in two pieces: an mmap()ed region from zero up to the
+     headersz, and a region updated via write() starting after that, containing
+     all the tables.  Platforms that do not support mmap() just use write().  */
+  ctf_startoffs = headersz;
+  if (lseek (fd, ctf_startoffs - 1, SEEK_SET) < 0)
+    {
+      errmsg = "ctf_arc_write(): cannot extend file while writing %s: %s\n";
+      goto err_close;
+    }
+
+  if (write (fd, &dummy, 1) < 0)
+    {
+      errmsg = "ctf_arc_write(): cannot extend file while writing %s: %s\n";
+      goto err_close;
+    }
+
+  if ((archdr = arc_mmap_header (fd, headersz)) == NULL)
+    {
+      errmsg = "ctf_arc_write(): Cannot mmap() %s: %s\n";
+      goto err_close;
+    }
+
+  /* Fill in everything we can, which is everything other than the name
+     table offset.  */
+  archdr->ctfa_magic = htole64 (CTFA_MAGIC);
+  archdr->ctfa_nfiles = htole64 (ctf_file_cnt);
+  archdr->ctfa_ctfs = htole64 (ctf_startoffs);
+
+  /* We could validate that all CTF files have the same data model, but
+     since any reasonable construction process will be building things of
+     only one bitness anyway, this is pretty pointless, so just use the
+     model of the first CTF file for all of them.  (It *is* valid to
+     create an empty archive: the value of ctfa_model is irrelevant in
+     this case, but we must be sure not to dereference uninitialized
+     memory.)  */
+
+  if (ctf_file_cnt > 0)
+    archdr->ctfa_model = htole64 (ctf_getmodel (ctf_files[0]));
+
+  /* Now write out the CTFs: ctf_archive_modent array via the mapping,
+     ctfs via write().  The names themselves have not been written yet: we
+     track them in a local strtab until the time is right, and sort the
+     modents array after construction.
+
+    The name table is not sorted.  */
+
+  for (i = 0, namesz = 0; i < le64toh (archdr->ctfa_nfiles); i++)
+    namesz += strlen (names[i]) + 1;
+
+  nametbl = malloc (namesz);
+  if (nametbl == NULL)
+    {
+      errmsg = "Error writing named CTF to %s: %s\n";
+      goto err_unmap;
+    }
+
+  for (i = 0, namesz = 0,
+       modent = (ctf_archive_modent_t *) ((char *) archdr
+					  + sizeof (struct ctf_archive));
+       i < le64toh (archdr->ctfa_nfiles); i++)
+    {
+      off_t off;
+
+      strcpy (&nametbl[namesz], names[i]);
+
+      off = arc_write_one_ctf (ctf_files[i], fd, threshold);
+      ctf_dprintf ("Written %s, offset now %zi\n", names[i], off);
+      if ((off < 0) && (off > -ECTF_BASE))
+	{
+	  errmsg = "ctf_arc_write(): Cannot determine file "
+	    "position while writing %s: %s";
+	  goto err_free;
+	}
+      if (off < 0)
+	{
+	  errmsg = "ctf_arc_write(): Cannot write CTF file to %s: %s\n";
+	  errno = off * -1;
+	  goto err_free;
+	}
+
+      modent->name_offset = htole64 (namesz);
+      modent->ctf_offset = htole64 (off - ctf_startoffs);
+      namesz += strlen (names[i]) + 1;
+      modent++;
+    }
+
+  qsort_r ((ctf_archive_modent_t *) ((char *) archdr
+				     + sizeof (struct ctf_archive)),
+	   le64toh (archdr->ctfa_nfiles),
+	   sizeof (struct ctf_archive_modent), sort_modent_by_name, nametbl);
+
+   /* Now the name table.  */
+
+  if ((nameoffs = lseek (fd, 0, SEEK_CUR)) < 0)
+    {
+      errmsg = "ctf_arc_write(): Cannot get current file position "
+	"in %s: %s\n";
+      goto err_free;
+    }
+  archdr->ctfa_names = htole64 (nameoffs);
+  np = nametbl;
+  while (namesz > 0)
+    {
+      ssize_t len;
+      if ((len = write (fd, np, namesz)) < 0)
+	{
+	  errmsg = "ctf_arc_write(): Cannot write name table in %s: %s\n";
+	  goto err_free;
+	}
+      namesz -= len;
+      np += len;
+    }
+  free (nametbl);
+
+  if (arc_mmap_writeout (fd, archdr, headersz, &errmsg) < 0)
+    goto err_unmap;
+  if (arc_mmap_unmap (archdr, headersz, &errmsg) < 0)
+    goto err_unlink;
+  if (close (fd) < 0)
+    {
+      errmsg = "ctf_arc_write(): Cannot close after writing to %s: %s\n";
+      goto err_unlink;
+    }
+
+  return 0;
+
+err_free:
+  free (nametbl);
+err_unmap:
+  arc_mmap_unmap (archdr, headersz, NULL);
+err_close:
+  close (fd);
+err_unlink:
+  unlink (file);
+err:
+  ctf_dprintf (errmsg, file, errno < ECTF_BASE ? strerror (errno) :
+	       ctf_errmsg (errno));
+  return errno;
+}
+
+/* Write one CTF file out.  Return the file position of the written file (or
+   rather, of the file-size uint64_t that precedes it): negative return is a
+   negative errno or ctf_errno value.  On error, the file position may no longer
+   be at the end of the file.  */
+static off_t
+arc_write_one_ctf (ctf_file_t * f, int fd, size_t threshold)
+{
+  off_t off, end_off;
+  uint64_t ctfsz = 0;
+  char *ctfszp;
+  size_t ctfsz_len;
+  int (*writefn) (ctf_file_t * fp, int fd);
+
+  if ((off = lseek (fd, 0, SEEK_CUR)) < 0)
+    return errno * -1;
+
+  if (f->ctf_size > threshold)
+    writefn = ctf_compress_write;
+  else
+    writefn = ctf_write;
+
+  /* This zero-write turns into the size in a moment. */
+  ctfsz_len = sizeof (ctfsz);
+  ctfszp = (char *) &ctfsz;
+  while (ctfsz_len > 0)
+    {
+      ssize_t writelen = write (fd, ctfszp, ctfsz_len);
+      if (writelen < 0)
+	return errno * -1;
+      ctfsz_len -= writelen;
+      ctfszp += writelen;
+    }
+
+  if (writefn (f, fd) != 0)
+    return f->ctf_errno * -1;
+
+  if ((end_off = lseek (fd, 0, SEEK_CUR)) < 0)
+    return errno * -1;
+  ctfsz = htole64 (end_off - off);
+
+  if ((lseek (fd, off, SEEK_SET)) < 0)
+    return errno * -1;
+
+  /* ... here.  */
+  ctfsz_len = sizeof (ctfsz);
+  ctfszp = (char *) &ctfsz;
+  while (ctfsz_len > 0)
+    {
+      ssize_t writelen = write (fd, ctfszp, ctfsz_len);
+      if (writelen < 0)
+	return errno * -1;
+      ctfsz_len -= writelen;
+      ctfszp += writelen;
+    }
+
+  end_off = LCTF_ALIGN_OFFS (end_off, 8);
+  if ((lseek (fd, end_off, SEEK_SET)) < 0)
+    return errno * -1;
+
+  return off;
+}
+
+/* qsort() function to sort the array of struct ctf_archive_modents into
+   ascending name order.  */
+static int
+sort_modent_by_name (const void *one, const void *two, void *n)
+{
+  const struct ctf_archive_modent *a = one;
+  const struct ctf_archive_modent *b = two;
+  char *nametbl = n;
+
+  return strcmp (&nametbl[le64toh (a->name_offset)],
+		 &nametbl[le64toh (b->name_offset)]);
+}
+
+/* bsearch() function to search for a given name in the sorted array of struct
+   ctf_archive_modents.  */
+static int
+search_modent_by_name (const void *key, const void *ent)
+{
+  const char *k = key;
+  const struct ctf_archive_modent *v = ent;
+
+  return strcmp (k, &search_nametbl[le64toh (v->name_offset)]);
+}
+
+/* Open a CTF archive.  Returns the archive, or NULL and an error in *err (if
+   not NULL).  */
+ctf_archive_t *
+ctf_arc_open (const char *filename, int *errp)
+{
+  const char *errmsg;
+  int fd;
+  struct stat s;
+  ctf_archive_t *arc;		/* (Actually the whole file.)  */
+
+  libctf_init_debug();
+  if ((fd = open (filename, O_RDONLY)) < 0)
+    {
+      errmsg = "ctf_arc_open(): cannot open %s: %s\n";
+      goto err;
+    }
+  if (fstat (fd, &s) < 0)
+    {
+      errmsg = "ctf_arc_open(): cannot stat %s: %s\n";
+      goto err_close;
+    }
+
+  if ((arc = arc_mmap_file (fd, s.st_size)) == NULL)
+    {
+      errmsg = "ctf_arc_open(): Cannot read in %s: %s\n";
+      goto err_close;
+    }
+
+  if (le64toh (arc->ctfa_magic) != CTFA_MAGIC)
+    {
+      errmsg = "ctf_arc_open(): Invalid magic number";
+      errno = ECTF_FMT;
+      goto err_unmap;
+    }
+
+  /* This horrible hack lets us know how much to unmap when the file is
+     closed.  (We no longer need the magic number, and the mapping
+     is private.)  */
+  arc->ctfa_magic = s.st_size;
+  close (fd);
+  return arc;
+
+err_unmap:
+  arc_mmap_unmap (arc, s.st_size, NULL);
+err_close:
+  close (fd);
+err:
+  if (errp)
+    *errp = errno;
+  ctf_dprintf (errmsg, filename, errno < ECTF_BASE ? strerror (errno) :
+	       ctf_errmsg (errno));
+  return NULL;
+}
+
+/* Close an archive.  */
+void
+ctf_arc_close (ctf_archive_t * arc)
+{
+  if (arc == NULL)
+    return;
+
+  /* See the comment in ctf_arc_open().  */
+  arc_mmap_unmap (arc, arc->ctfa_magic, NULL);
+}
+
+/* Return the ctf_file_t with the given name, or NULL if none, setting 'err' if
+   non-NULL.  */
+ctf_file_t *
+ctf_arc_open_by_name (const ctf_archive_t * arc, const char *name, int *errp)
+{
+  struct ctf_archive_modent *modent;
+
+  ctf_dprintf ("ctf_arc_open_by_name(%s): opening\n", name);
+
+  modent = (ctf_archive_modent_t *) ((char *) arc
+				     + sizeof (struct ctf_archive));
+
+  search_nametbl = (char *) arc + le64toh (arc->ctfa_names);
+  modent = bsearch (name, modent, le64toh (arc->ctfa_nfiles),
+		    sizeof (struct ctf_archive_modent),
+		    search_modent_by_name);
+
+  /* This is actually a common case and normal operation: no error
+     debug output.  */
+  if (modent == NULL)
+    {
+      if (errp)
+	*errp = ECTF_ARNNAME;
+      return NULL;
+    }
+
+  return ctf_arc_open_by_offset (arc, le64toh (modent->ctf_offset), errp);
+}
+
+/* Return the ctf_file_t at the given ctfa_ctfs-relative offset, or NULL if
+   none, setting 'err' if non-NULL.  */
+static ctf_file_t *
+ctf_arc_open_by_offset (const ctf_archive_t *arc, size_t offset, int *errp)
+{
+  ctf_sect_t ctfsect;
+  ctf_file_t *fp;
+
+  ctf_dprintf ("ctf_arc_open_by_offset(%zi): opening\n", offset);
+
+  bzero (&ctfsect, sizeof (ctf_sect_t));
+
+  offset += le64toh (arc->ctfa_ctfs);
+
+  ctfsect.cts_name = _CTF_SECTION;
+  ctfsect.cts_type = SHT_PROGBITS;
+  ctfsect.cts_flags = SHF_ALLOC;
+  ctfsect.cts_size = le64toh (*((uint64_t *) ((char *) arc + offset)));
+  ctfsect.cts_entsize = 1;
+  ctfsect.cts_offset = 0;
+  ctfsect.cts_data = (void *) ((char *) arc + offset + sizeof (uint64_t));
+  fp = ctf_bufopen (&ctfsect, NULL, NULL, errp);
+  if (fp)
+    ctf_setmodel (fp, le64toh (arc->ctfa_model));
+  return fp;
+}
+
+/* Iterate over all CTF files in an archive.  We pass the raw data for all CTF
+   files in turn to the specified callback function.  */
+int
+ctf_archive_raw_iter (const ctf_archive_t * arc,
+		      ctf_archive_raw_member_f * func, void *data)
+{
+  int rc;
+  size_t i;
+  struct ctf_archive_modent *modent;
+  const char *nametbl;
+
+  modent = (ctf_archive_modent_t *) ((char *) arc
+				     + sizeof (struct ctf_archive));
+  nametbl = (((const char *) arc) + le64toh (arc->ctfa_names));
+
+  for (i = 0; i < le64toh (arc->ctfa_nfiles); i++)
+    {
+      const char *name;
+      char *fp;
+
+      name = &nametbl[le64toh (modent[i].name_offset)];
+      fp = ((char *) arc + le64toh (arc->ctfa_ctfs)
+	    + le64toh (modent[i].ctf_offset));
+
+      if ((rc = func (name, (void *) (fp + sizeof (uint64_t)),
+		      le64toh (*((uint64_t *) fp)), data)) != 0)
+	return rc;
+    }
+  return 0;
+}
+
+/* Iterate over all CTF files in an archive.  We pass all CTF files in turn to
+   the specified callback function.  */
+int
+ctf_archive_iter (const ctf_archive_t * arc, ctf_archive_member_f * func,
+		  void *data)
+{
+  int rc;
+  size_t i;
+  ctf_file_t *f;
+  struct ctf_archive_modent *modent;
+  const char *nametbl;
+
+  modent = (ctf_archive_modent_t *) ((char *) arc
+				     + sizeof (struct ctf_archive));
+  nametbl = (((const char *) arc) + le64toh (arc->ctfa_names));
+
+  for (i = 0; i < le64toh (arc->ctfa_nfiles); i++)
+    {
+      const char *name;
+
+      name = &nametbl[le64toh (modent[i].name_offset)];
+      if ((f = ctf_arc_open_by_name (arc, name, &rc)) == NULL)
+	return rc;
+
+      if ((rc = func (f, name, data)) != 0)
+	{
+	  ctf_close (f);
+	  return rc;
+	}
+
+      ctf_close (f);
+    }
+  return 0;
+}
+
+#ifdef HAVE_MMAP
+/* Map the header in.  Only used on new, empty files.  */
+static void *arc_mmap_header (int fd, size_t headersz)
+{
+  void *hdr;
+  if ((hdr = mmap (NULL, headersz, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
+		   0)) == MAP_FAILED)
+    return NULL;
+  return hdr;
+}
+
+/* mmap() the whole file, for reading only.  (Map it writably, but privately: we
+   need to modify the region, but don't need anyone else to see the
+   modifications.)  */
+static void *arc_mmap_file (int fd, size_t size)
+{
+  void *arc;
+  if ((arc = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
+		   fd, 0)) == MAP_FAILED)
+    return NULL;
+  return arc;
+}
+
+/* Persist the header to disk.  */
+static int arc_mmap_writeout (int fd _libctf_unused_, void *header,
+			      size_t headersz, const char **errmsg)
+{
+    if (msync (header, headersz, MS_ASYNC) < 0)
+    {
+      if (errmsg)
+	*errmsg = "arc_mmap_writeout(): Cannot sync after writing to %s: %s\n";
+      return -1;
+    }
+    return 0;
+}
+
+/* Unmap the region.  */
+static int arc_mmap_unmap (void *header, size_t headersz, const char **errmsg)
+{
+  if (munmap (header, headersz) < 0)
+    {
+      if (errmsg)
+	*errmsg = "arc_mmap_munmap(): Cannot unmap after writing to %s: %s\n";
+      return -1;
+    }
+    return 0;
+}
+#else
+/* Map the header in.  Only used on new, empty files.  */
+static void *arc_mmap_header (int fd, size_t headersz)
+{
+  void *hdr;
+  if ((hdr = malloc (headersz)) == NULL)
+    return NULL;
+  return hdr;
+}
+
+/* Pull in the whole file, for reading only.  We assume the current file
+   position is at the start of the file.  */
+static void *arc_mmap_file (int fd, size_t size)
+{
+  char *data;
+
+  if ((data = malloc (size)) == NULL)
+    return NULL;
+
+  if (ctf_pread (fd, data, size, 0) < 0)
+    {
+      free (data);
+      return NULL;
+    }
+  return data;
+}
+
+/* Persist the header to disk.  */
+static int arc_mmap_writeout (int fd, void *header, size_t headersz,
+			      const char **errmsg)
+{
+  ssize_t len;
+  size_t acc = 0;
+  char *data = (char *) header;
+  ssize_t count = headersz;
+
+  if ((lseek (fd, 0, SEEK_SET)) < 0)
+    {
+      if (errmsg)
+	*errmsg = "arc_mmap_writeout(): Cannot seek while writing header to "
+	  "%s: %s\n";
+      return -1;
+    }
+
+  while (headersz > 0)
+    {
+      if ((len = write (fd, data, count)) < 0)
+	{
+	  if (errmsg)
+	    *errmsg = "arc_mmap_writeout(): Cannot write header to %s: %s\n";
+	  return len;
+	}
+      if (len == EINTR)
+	continue;
+
+      acc += len;
+      if (len == 0)				/* EOF.  */
+	break;
+
+      count -= len;
+      data += len;
+    }
+  return 0;
+}
+
+/* Unmap the region.  */
+static int arc_mmap_unmap (void *header, size_t headersz _libctf_unused_,
+			   const char **errmsg _libctf_unused_)
+{
+  free (header);
+  return 0;
+}
+#endif
-- 
2.21.0.237.gd0cfaa883d

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v2 14/19] libctf: library version enforcement
  2019-05-17 22:10 [PATCH v2 00/19] libctf, and CTF support for objdump and readelf Nick Alcock
                   ` (8 preceding siblings ...)
  2019-05-17 22:10 ` [PATCH v2 15/19] libctf: mmappable archives Nick Alcock
@ 2019-05-17 22:10 ` Nick Alcock
  2019-05-17 22:10 ` [PATCH v2 08/19] libctf: creation functions Nick Alcock
                   ` (10 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nick Alcock @ 2019-05-17 22:10 UTC (permalink / raw)
  To: binutils

This old Solaris standard allows callers to specify that they are
expecting one particular API and/or CTF file format from the library.

It is basically vestigial and I would be amenable to dropping it.

Changes from v1:
 - Correct erroneous license (GPLv2+ -> v3+) and reset copyright years.
 - Adjust to ctf_free() prototype changes
 - Migrate into ctf-subr.c, since ctf-lib.c is gone

libctf/
	* ctf-impl.h (_libctf_version): New declaration.
	* ctf-subr.c (_libctf_version): Define it.
	(ctf_version): New.

include/
	* ctf-api.h (ctf_version): New.
---
 include/ctf-api.h |  1 +
 libctf/ctf-impl.h |  1 +
 libctf/ctf-subr.c | 27 +++++++++++++++++++++++++++
 3 files changed, 29 insertions(+)

diff --git a/include/ctf-api.h b/include/ctf-api.h
index 049062ea80..81f790dafd 100644
--- a/include/ctf-api.h
+++ b/include/ctf-api.h
@@ -239,6 +239,7 @@ extern void *ctf_getspecific (ctf_file_t *);
 
 extern int ctf_errno (ctf_file_t *);
 extern const char *ctf_errmsg (int);
+extern int ctf_version (int);
 
 extern int ctf_func_info (ctf_file_t *, unsigned long, ctf_funcinfo_t *);
 extern int ctf_func_args (ctf_file_t *, unsigned long, uint32_t, ctf_id_t *);
diff --git a/libctf/ctf-impl.h b/libctf/ctf-impl.h
index 91c46d5d5a..a067e0f4d0 100644
--- a/libctf/ctf-impl.h
+++ b/libctf/ctf-impl.h
@@ -364,6 +364,7 @@ extern const char *ctf_lookup_symbol_name (ctf_file_t *fp, unsigned long symidx)
 extern const char _CTF_SECTION[];	/* name of CTF ELF section */
 extern const char _CTF_NULLSTR[];	/* empty string */
 
+extern int _libctf_version;	/* library client version */
 extern int _libctf_debug;	/* debugging messages enabled */
 
 #ifdef	__cplusplus
diff --git a/libctf/ctf-subr.c b/libctf/ctf-subr.c
index 3103e28a3f..09ec2951e5 100644
--- a/libctf/ctf-subr.c
+++ b/libctf/ctf-subr.c
@@ -27,6 +27,7 @@
 #include <unistd.h>
 
 static size_t _PAGESIZE _libctf_unused_;
+int _libctf_version = CTF_VERSION;	      /* Library client version.  */
 int _libctf_debug = 0;			      /* Debugging messages enabled.  */
 
 _libctf_malloc_ void *
@@ -190,6 +191,32 @@ ctf_strerror (int err)
   return (const char *) (strerror (err));
 }
 
+/* Set the CTF library client version to the specified version.  If version is
+   zero, we just return the default library version number.  */
+int
+ctf_version (int version)
+{
+  if (version < 0)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  if (version > 0)
+    {
+      /*  Dynamic version switching is not presently supported. */
+      if (version != CTF_VERSION)
+	{
+	  errno = ENOTSUP;
+	  return -1;
+	}
+      ctf_dprintf ("ctf_version: client using version %d\n", version);
+      _libctf_version = version;
+    }
+
+  return _libctf_version;
+}
+
 void
 libctf_init_debug (void)
 {
-- 
2.21.0.237.gd0cfaa883d

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v2 18/19] libctf: build system
  2019-05-17 22:10 [PATCH v2 00/19] libctf, and CTF support for objdump and readelf Nick Alcock
                   ` (15 preceding siblings ...)
  2019-05-17 22:10 ` [PATCH v2 02/19] include: new header ctf-api.h Nick Alcock
@ 2019-05-17 22:11 ` Nick Alcock
  2019-05-17 22:12 ` [PATCH v2 16/19] libctf: labels Nick Alcock
                   ` (3 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nick Alcock @ 2019-05-17 22:11 UTC (permalink / raw)
  To: binutils

This ties libctf into the build system, and makes binutils depend on it
(used by the next commits).

Changes from v1:
 - libctf now depends on bfd, and gets includes from it
 - ctf-lib.c is gone: ctf-open-bfd.c is new.
 - We now check for mmap, byteswap.h and pread.

	* Makefile.def (host_modules): Add libctf.
	* Makefile.def (dependencies): Likewise.
	libctf depends on zlib, libiberty, and bfd.
	* Makefile.in: Regenerated.
	* configure.ac (host_libs): Add libctf.
	* configure: Regenerated.

libctf/
	* Makefile.am: New.
	* Makefile.in: Regenerated.
	* config.h.in: Likewise.
	* aclocal.m4: Likewise.
	* configure: Likewise.
---
 Makefile.def        |    6 +
 Makefile.in         |  991 +++++-
 configure           |    2 +-
 configure.ac        |    2 +-
 libctf/Makefile.am  |   31 +
 libctf/Makefile.in  |  767 +++++
 libctf/aclocal.m4   | 1233 +++++++
 libctf/config.h.in  |  113 +
 libctf/configure    | 7462 +++++++++++++++++++++++++++++++++++++++++++
 libctf/configure.ac |   63 +
 10 files changed, 10663 insertions(+), 7 deletions(-)
 create mode 100644 libctf/Makefile.am
 create mode 100644 libctf/Makefile.in
 create mode 100644 libctf/aclocal.m4
 create mode 100644 libctf/config.h.in
 create mode 100755 libctf/configure
 create mode 100644 libctf/configure.ac

diff --git a/Makefile.def b/Makefile.def
index 75063b6d12..3aa03b45d3 100644
--- a/Makefile.def
+++ b/Makefile.def
@@ -128,6 +128,8 @@ host_modules= { module= lto-plugin; bootstrap=true;
 		extra_make_flags='@extra_linker_plugin_flags@'; };
 host_modules= { module= libcc1; extra_configure_flags=--enable-shared; };
 host_modules= { module= gotools; };
+host_modules= { module= libctf; no_install=true; no_check=true;
+		bootstrap=true; };
 
 target_modules = { module= libstdc++-v3;
 		   bootstrap=true;
@@ -426,6 +428,7 @@ dependencies = { module=all-binutils; on=all-build-flex; };
 dependencies = { module=all-binutils; on=all-build-bison; };
 dependencies = { module=all-binutils; on=all-intl; };
 dependencies = { module=all-binutils; on=all-gas; };
+dependencies = { module=all-binutils; 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
@@ -516,6 +519,9 @@ dependencies = { module=all-sim; on=configure-gdb; };
 dependencies = { module=all-fastjar; on=all-zlib; };
 dependencies = { module=all-fastjar; on=all-build-texinfo; };
 dependencies = { module=all-fastjar; on=all-libiberty; };
+dependencies = { module=all-libctf; on=all-libiberty; hard=true; };
+dependencies = { module=all-libctf; on=all-bfd; };
+dependencies = { module=all-libctf; on=all-zlib; };
 
 // Warning, these are not well tested.
 dependencies = { module=all-bison; on=all-intl; };
diff --git a/Makefile.in b/Makefile.in
index 7814fe745f..68675f0479 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -951,7 +951,8 @@ configure-host:  \
     maybe-configure-gnattools \
     maybe-configure-lto-plugin \
     maybe-configure-libcc1 \
-    maybe-configure-gotools
+    maybe-configure-gotools \
+    maybe-configure-libctf
 .PHONY: configure-target
 configure-target:  \
     maybe-configure-target-libstdc++-v3 \
@@ -1106,6 +1107,9 @@ all-host: maybe-all-lto-plugin
 @endif lto-plugin-no-bootstrap
 all-host: maybe-all-libcc1
 all-host: maybe-all-gotools
+@if libctf-no-bootstrap
+all-host: maybe-all-libctf
+@endif libctf-no-bootstrap
 
 .PHONY: all-target
 
@@ -1208,6 +1212,7 @@ info-host: maybe-info-gnattools
 info-host: maybe-info-lto-plugin
 info-host: maybe-info-libcc1
 info-host: maybe-info-gotools
+info-host: maybe-info-libctf
 
 .PHONY: info-target
 
@@ -1293,6 +1298,7 @@ dvi-host: maybe-dvi-gnattools
 dvi-host: maybe-dvi-lto-plugin
 dvi-host: maybe-dvi-libcc1
 dvi-host: maybe-dvi-gotools
+dvi-host: maybe-dvi-libctf
 
 .PHONY: dvi-target
 
@@ -1378,6 +1384,7 @@ pdf-host: maybe-pdf-gnattools
 pdf-host: maybe-pdf-lto-plugin
 pdf-host: maybe-pdf-libcc1
 pdf-host: maybe-pdf-gotools
+pdf-host: maybe-pdf-libctf
 
 .PHONY: pdf-target
 
@@ -1463,6 +1470,7 @@ html-host: maybe-html-gnattools
 html-host: maybe-html-lto-plugin
 html-host: maybe-html-libcc1
 html-host: maybe-html-gotools
+html-host: maybe-html-libctf
 
 .PHONY: html-target
 
@@ -1548,6 +1556,7 @@ TAGS-host: maybe-TAGS-gnattools
 TAGS-host: maybe-TAGS-lto-plugin
 TAGS-host: maybe-TAGS-libcc1
 TAGS-host: maybe-TAGS-gotools
+TAGS-host: maybe-TAGS-libctf
 
 .PHONY: TAGS-target
 
@@ -1633,6 +1642,7 @@ install-info-host: maybe-install-info-gnattools
 install-info-host: maybe-install-info-lto-plugin
 install-info-host: maybe-install-info-libcc1
 install-info-host: maybe-install-info-gotools
+install-info-host: maybe-install-info-libctf
 
 .PHONY: install-info-target
 
@@ -1718,6 +1728,7 @@ install-pdf-host: maybe-install-pdf-gnattools
 install-pdf-host: maybe-install-pdf-lto-plugin
 install-pdf-host: maybe-install-pdf-libcc1
 install-pdf-host: maybe-install-pdf-gotools
+install-pdf-host: maybe-install-pdf-libctf
 
 .PHONY: install-pdf-target
 
@@ -1803,6 +1814,7 @@ install-html-host: maybe-install-html-gnattools
 install-html-host: maybe-install-html-lto-plugin
 install-html-host: maybe-install-html-libcc1
 install-html-host: maybe-install-html-gotools
+install-html-host: maybe-install-html-libctf
 
 .PHONY: install-html-target
 
@@ -1888,6 +1900,7 @@ installcheck-host: maybe-installcheck-gnattools
 installcheck-host: maybe-installcheck-lto-plugin
 installcheck-host: maybe-installcheck-libcc1
 installcheck-host: maybe-installcheck-gotools
+installcheck-host: maybe-installcheck-libctf
 
 .PHONY: installcheck-target
 
@@ -1973,6 +1986,7 @@ mostlyclean-host: maybe-mostlyclean-gnattools
 mostlyclean-host: maybe-mostlyclean-lto-plugin
 mostlyclean-host: maybe-mostlyclean-libcc1
 mostlyclean-host: maybe-mostlyclean-gotools
+mostlyclean-host: maybe-mostlyclean-libctf
 
 .PHONY: mostlyclean-target
 
@@ -2058,6 +2072,7 @@ clean-host: maybe-clean-gnattools
 clean-host: maybe-clean-lto-plugin
 clean-host: maybe-clean-libcc1
 clean-host: maybe-clean-gotools
+clean-host: maybe-clean-libctf
 
 .PHONY: clean-target
 
@@ -2143,6 +2158,7 @@ distclean-host: maybe-distclean-gnattools
 distclean-host: maybe-distclean-lto-plugin
 distclean-host: maybe-distclean-libcc1
 distclean-host: maybe-distclean-gotools
+distclean-host: maybe-distclean-libctf
 
 .PHONY: distclean-target
 
@@ -2228,6 +2244,7 @@ maintainer-clean-host: maybe-maintainer-clean-gnattools
 maintainer-clean-host: maybe-maintainer-clean-lto-plugin
 maintainer-clean-host: maybe-maintainer-clean-libcc1
 maintainer-clean-host: maybe-maintainer-clean-gotools
+maintainer-clean-host: maybe-maintainer-clean-libctf
 
 .PHONY: maintainer-clean-target
 
@@ -2368,7 +2385,8 @@ check-host:  \
     maybe-check-gnattools \
     maybe-check-lto-plugin \
     maybe-check-libcc1 \
-    maybe-check-gotools
+    maybe-check-gotools \
+    maybe-check-libctf
 
 .PHONY: check-target
 check-target:  \
@@ -2500,7 +2518,8 @@ install-host-nogcc:  \
     maybe-install-gnattools \
     maybe-install-lto-plugin \
     maybe-install-libcc1 \
-    maybe-install-gotools
+    maybe-install-gotools \
+    maybe-install-libctf
 
 .PHONY: install-host
 install-host:  \
@@ -2549,7 +2568,8 @@ install-host:  \
     maybe-install-gnattools \
     maybe-install-lto-plugin \
     maybe-install-libcc1 \
-    maybe-install-gotools
+    maybe-install-gotools \
+    maybe-install-libctf
 
 .PHONY: install-target
 install-target:  \
@@ -2654,7 +2674,8 @@ install-strip-host:  \
     maybe-install-strip-gnattools \
     maybe-install-strip-lto-plugin \
     maybe-install-strip-libcc1 \
-    maybe-install-strip-gotools
+    maybe-install-strip-gotools \
+    maybe-install-strip-libctf
 
 .PHONY: install-strip-target
 install-strip-target:  \
@@ -32847,6 +32868,868 @@ maintainer-clean-gotools:
 
 
 
+.PHONY: configure-libctf maybe-configure-libctf
+maybe-configure-libctf:
+@if gcc-bootstrap
+configure-libctf: stage_current
+@endif gcc-bootstrap
+@if libctf
+maybe-configure-libctf: configure-libctf
+configure-libctf: 
+	@r=`${PWD_COMMAND}`; export r; \
+	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+	test ! -f $(HOST_SUBDIR)/libctf/Makefile || exit 0; \
+	$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/libctf; \
+	$(HOST_EXPORTS)  \
+	echo Configuring in $(HOST_SUBDIR)/libctf; \
+	cd "$(HOST_SUBDIR)/libctf" || exit 1; \
+	case $(srcdir) in \
+	  /* | [A-Za-z]:[\\/]*) topdir=$(srcdir) ;; \
+	  *) topdir=`echo $(HOST_SUBDIR)/libctf/ | \
+		sed -e 's,\./,,g' -e 's,[^/]*/,../,g' `$(srcdir) ;; \
+	esac; \
+	module_srcdir=libctf; \
+	$(SHELL) \
+	  $$s/$$module_srcdir/configure \
+	  --srcdir=$${topdir}/$$module_srcdir \
+	  $(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \
+	  --target=${target_alias}  \
+	  || exit 1
+@endif libctf
+
+
+
+.PHONY: configure-stage1-libctf maybe-configure-stage1-libctf
+maybe-configure-stage1-libctf:
+@if libctf-bootstrap
+maybe-configure-stage1-libctf: configure-stage1-libctf
+configure-stage1-libctf:
+	@[ $(current_stage) = stage1 ] || $(MAKE) stage1-start
+	@$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/libctf
+	@r=`${PWD_COMMAND}`; export r; \
+	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+	TFLAGS="$(STAGE1_TFLAGS)"; \
+	test ! -f $(HOST_SUBDIR)/libctf/Makefile || exit 0; \
+	$(HOST_EXPORTS) \
+	CFLAGS="$(STAGE1_CFLAGS)"; export CFLAGS; \
+	CXXFLAGS="$(STAGE1_CXXFLAGS)"; export CXXFLAGS; \
+	LIBCFLAGS="$(LIBCFLAGS)"; export LIBCFLAGS;  \
+	echo Configuring stage 1 in $(HOST_SUBDIR)/libctf; \
+	$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/libctf; \
+	cd $(HOST_SUBDIR)/libctf || exit 1; \
+	case $(srcdir) in \
+	  /* | [A-Za-z]:[\\/]*) topdir=$(srcdir) ;; \
+	  *) topdir=`echo $(HOST_SUBDIR)/libctf/ | \
+		sed -e 's,\./,,g' -e 's,[^/]*/,../,g' `$(srcdir) ;; \
+	esac; \
+	module_srcdir=libctf; \
+	$(SHELL) $$s/$$module_srcdir/configure \
+	  --srcdir=$${topdir}/$$module_srcdir \
+	  $(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \
+	  --target=${target_alias} \
+	   \
+	  $(STAGE1_CONFIGURE_FLAGS)
+@endif libctf-bootstrap
+
+.PHONY: configure-stage2-libctf maybe-configure-stage2-libctf
+maybe-configure-stage2-libctf:
+@if libctf-bootstrap
+maybe-configure-stage2-libctf: configure-stage2-libctf
+configure-stage2-libctf:
+	@[ $(current_stage) = stage2 ] || $(MAKE) stage2-start
+	@$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/libctf
+	@r=`${PWD_COMMAND}`; export r; \
+	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+	TFLAGS="$(STAGE2_TFLAGS)"; \
+	test ! -f $(HOST_SUBDIR)/libctf/Makefile || exit 0; \
+	$(HOST_EXPORTS) \
+	$(POSTSTAGE1_HOST_EXPORTS) \
+	CFLAGS="$(STAGE2_CFLAGS)"; export CFLAGS; \
+	CXXFLAGS="$(STAGE2_CXXFLAGS)"; export CXXFLAGS; \
+	LIBCFLAGS="$(STAGE2_CFLAGS)"; export LIBCFLAGS;  \
+	echo Configuring stage 2 in $(HOST_SUBDIR)/libctf; \
+	$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/libctf; \
+	cd $(HOST_SUBDIR)/libctf || exit 1; \
+	case $(srcdir) in \
+	  /* | [A-Za-z]:[\\/]*) topdir=$(srcdir) ;; \
+	  *) topdir=`echo $(HOST_SUBDIR)/libctf/ | \
+		sed -e 's,\./,,g' -e 's,[^/]*/,../,g' `$(srcdir) ;; \
+	esac; \
+	module_srcdir=libctf; \
+	$(SHELL) $$s/$$module_srcdir/configure \
+	  --srcdir=$${topdir}/$$module_srcdir \
+	  $(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \
+	  --target=${target_alias} \
+	  --with-build-libsubdir=$(HOST_SUBDIR) \
+	  $(STAGE2_CONFIGURE_FLAGS)
+@endif libctf-bootstrap
+
+.PHONY: configure-stage3-libctf maybe-configure-stage3-libctf
+maybe-configure-stage3-libctf:
+@if libctf-bootstrap
+maybe-configure-stage3-libctf: configure-stage3-libctf
+configure-stage3-libctf:
+	@[ $(current_stage) = stage3 ] || $(MAKE) stage3-start
+	@$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/libctf
+	@r=`${PWD_COMMAND}`; export r; \
+	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+	TFLAGS="$(STAGE3_TFLAGS)"; \
+	test ! -f $(HOST_SUBDIR)/libctf/Makefile || exit 0; \
+	$(HOST_EXPORTS) \
+	$(POSTSTAGE1_HOST_EXPORTS) \
+	CFLAGS="$(STAGE3_CFLAGS)"; export CFLAGS; \
+	CXXFLAGS="$(STAGE3_CXXFLAGS)"; export CXXFLAGS; \
+	LIBCFLAGS="$(STAGE3_CFLAGS)"; export LIBCFLAGS;  \
+	echo Configuring stage 3 in $(HOST_SUBDIR)/libctf; \
+	$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/libctf; \
+	cd $(HOST_SUBDIR)/libctf || exit 1; \
+	case $(srcdir) in \
+	  /* | [A-Za-z]:[\\/]*) topdir=$(srcdir) ;; \
+	  *) topdir=`echo $(HOST_SUBDIR)/libctf/ | \
+		sed -e 's,\./,,g' -e 's,[^/]*/,../,g' `$(srcdir) ;; \
+	esac; \
+	module_srcdir=libctf; \
+	$(SHELL) $$s/$$module_srcdir/configure \
+	  --srcdir=$${topdir}/$$module_srcdir \
+	  $(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \
+	  --target=${target_alias} \
+	  --with-build-libsubdir=$(HOST_SUBDIR) \
+	  $(STAGE3_CONFIGURE_FLAGS)
+@endif libctf-bootstrap
+
+.PHONY: configure-stage4-libctf maybe-configure-stage4-libctf
+maybe-configure-stage4-libctf:
+@if libctf-bootstrap
+maybe-configure-stage4-libctf: configure-stage4-libctf
+configure-stage4-libctf:
+	@[ $(current_stage) = stage4 ] || $(MAKE) stage4-start
+	@$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/libctf
+	@r=`${PWD_COMMAND}`; export r; \
+	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+	TFLAGS="$(STAGE4_TFLAGS)"; \
+	test ! -f $(HOST_SUBDIR)/libctf/Makefile || exit 0; \
+	$(HOST_EXPORTS) \
+	$(POSTSTAGE1_HOST_EXPORTS) \
+	CFLAGS="$(STAGE4_CFLAGS)"; export CFLAGS; \
+	CXXFLAGS="$(STAGE4_CXXFLAGS)"; export CXXFLAGS; \
+	LIBCFLAGS="$(STAGE4_CFLAGS)"; export LIBCFLAGS;  \
+	echo Configuring stage 4 in $(HOST_SUBDIR)/libctf; \
+	$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/libctf; \
+	cd $(HOST_SUBDIR)/libctf || exit 1; \
+	case $(srcdir) in \
+	  /* | [A-Za-z]:[\\/]*) topdir=$(srcdir) ;; \
+	  *) topdir=`echo $(HOST_SUBDIR)/libctf/ | \
+		sed -e 's,\./,,g' -e 's,[^/]*/,../,g' `$(srcdir) ;; \
+	esac; \
+	module_srcdir=libctf; \
+	$(SHELL) $$s/$$module_srcdir/configure \
+	  --srcdir=$${topdir}/$$module_srcdir \
+	  $(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \
+	  --target=${target_alias} \
+	  --with-build-libsubdir=$(HOST_SUBDIR) \
+	  $(STAGE4_CONFIGURE_FLAGS)
+@endif libctf-bootstrap
+
+.PHONY: configure-stageprofile-libctf maybe-configure-stageprofile-libctf
+maybe-configure-stageprofile-libctf:
+@if libctf-bootstrap
+maybe-configure-stageprofile-libctf: configure-stageprofile-libctf
+configure-stageprofile-libctf:
+	@[ $(current_stage) = stageprofile ] || $(MAKE) stageprofile-start
+	@$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/libctf
+	@r=`${PWD_COMMAND}`; export r; \
+	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+	TFLAGS="$(STAGEprofile_TFLAGS)"; \
+	test ! -f $(HOST_SUBDIR)/libctf/Makefile || exit 0; \
+	$(HOST_EXPORTS) \
+	$(POSTSTAGE1_HOST_EXPORTS) \
+	CFLAGS="$(STAGEprofile_CFLAGS)"; export CFLAGS; \
+	CXXFLAGS="$(STAGEprofile_CXXFLAGS)"; export CXXFLAGS; \
+	LIBCFLAGS="$(STAGEprofile_CFLAGS)"; export LIBCFLAGS;  \
+	echo Configuring stage profile in $(HOST_SUBDIR)/libctf; \
+	$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/libctf; \
+	cd $(HOST_SUBDIR)/libctf || exit 1; \
+	case $(srcdir) in \
+	  /* | [A-Za-z]:[\\/]*) topdir=$(srcdir) ;; \
+	  *) topdir=`echo $(HOST_SUBDIR)/libctf/ | \
+		sed -e 's,\./,,g' -e 's,[^/]*/,../,g' `$(srcdir) ;; \
+	esac; \
+	module_srcdir=libctf; \
+	$(SHELL) $$s/$$module_srcdir/configure \
+	  --srcdir=$${topdir}/$$module_srcdir \
+	  $(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \
+	  --target=${target_alias} \
+	  --with-build-libsubdir=$(HOST_SUBDIR) \
+	  $(STAGEprofile_CONFIGURE_FLAGS)
+@endif libctf-bootstrap
+
+.PHONY: configure-stagefeedback-libctf maybe-configure-stagefeedback-libctf
+maybe-configure-stagefeedback-libctf:
+@if libctf-bootstrap
+maybe-configure-stagefeedback-libctf: configure-stagefeedback-libctf
+configure-stagefeedback-libctf:
+	@[ $(current_stage) = stagefeedback ] || $(MAKE) stagefeedback-start
+	@$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/libctf
+	@r=`${PWD_COMMAND}`; export r; \
+	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+	TFLAGS="$(STAGEfeedback_TFLAGS)"; \
+	test ! -f $(HOST_SUBDIR)/libctf/Makefile || exit 0; \
+	$(HOST_EXPORTS) \
+	$(POSTSTAGE1_HOST_EXPORTS) \
+	CFLAGS="$(STAGEfeedback_CFLAGS)"; export CFLAGS; \
+	CXXFLAGS="$(STAGEfeedback_CXXFLAGS)"; export CXXFLAGS; \
+	LIBCFLAGS="$(STAGEfeedback_CFLAGS)"; export LIBCFLAGS;  \
+	echo Configuring stage feedback in $(HOST_SUBDIR)/libctf; \
+	$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/libctf; \
+	cd $(HOST_SUBDIR)/libctf || exit 1; \
+	case $(srcdir) in \
+	  /* | [A-Za-z]:[\\/]*) topdir=$(srcdir) ;; \
+	  *) topdir=`echo $(HOST_SUBDIR)/libctf/ | \
+		sed -e 's,\./,,g' -e 's,[^/]*/,../,g' `$(srcdir) ;; \
+	esac; \
+	module_srcdir=libctf; \
+	$(SHELL) $$s/$$module_srcdir/configure \
+	  --srcdir=$${topdir}/$$module_srcdir \
+	  $(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \
+	  --target=${target_alias} \
+	  --with-build-libsubdir=$(HOST_SUBDIR) \
+	  $(STAGEfeedback_CONFIGURE_FLAGS)
+@endif libctf-bootstrap
+
+
+
+
+
+.PHONY: all-libctf maybe-all-libctf
+maybe-all-libctf:
+@if gcc-bootstrap
+all-libctf: stage_current
+@endif gcc-bootstrap
+@if libctf
+TARGET-libctf=all
+maybe-all-libctf: all-libctf
+all-libctf: configure-libctf
+	@r=`${PWD_COMMAND}`; export r; \
+	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+	$(HOST_EXPORTS)  \
+	(cd $(HOST_SUBDIR)/libctf && \
+	  $(MAKE) $(BASE_FLAGS_TO_PASS) $(EXTRA_HOST_FLAGS) $(STAGE1_FLAGS_TO_PASS)  \
+		$(TARGET-libctf))
+@endif libctf
+
+
+
+.PHONY: all-stage1-libctf maybe-all-stage1-libctf
+.PHONY: clean-stage1-libctf maybe-clean-stage1-libctf
+maybe-all-stage1-libctf:
+maybe-clean-stage1-libctf:
+@if libctf-bootstrap
+maybe-all-stage1-libctf: all-stage1-libctf
+all-stage1: all-stage1-libctf
+TARGET-stage1-libctf = $(TARGET-libctf)
+all-stage1-libctf: configure-stage1-libctf
+	@[ $(current_stage) = stage1 ] || $(MAKE) stage1-start
+	@r=`${PWD_COMMAND}`; export r; \
+	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+	TFLAGS="$(STAGE1_TFLAGS)"; \
+	$(HOST_EXPORTS)  \
+	cd $(HOST_SUBDIR)/libctf && \
+	 \
+	$(MAKE) $(BASE_FLAGS_TO_PASS) \
+		CFLAGS="$(STAGE1_CFLAGS)" \
+		CXXFLAGS="$(STAGE1_CXXFLAGS)" \
+		LIBCFLAGS="$(LIBCFLAGS)" \
+		CFLAGS_FOR_TARGET="$(CFLAGS_FOR_TARGET)" \
+		CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" \
+		LIBCFLAGS_FOR_TARGET="$(LIBCFLAGS_FOR_TARGET)" \
+		$(EXTRA_HOST_FLAGS)  \
+		$(STAGE1_FLAGS_TO_PASS)  \
+		TFLAGS="$(STAGE1_TFLAGS)"  \
+		$(TARGET-stage1-libctf)
+
+maybe-clean-stage1-libctf: clean-stage1-libctf
+clean-stage1: clean-stage1-libctf
+clean-stage1-libctf:
+	@if [ $(current_stage) = stage1 ]; then \
+	  [ -f $(HOST_SUBDIR)/libctf/Makefile ] || exit 0; \
+	else \
+	  [ -f $(HOST_SUBDIR)/stage1-libctf/Makefile ] || exit 0; \
+	  $(MAKE) stage1-start; \
+	fi; \
+	cd $(HOST_SUBDIR)/libctf && \
+	$(MAKE) $(EXTRA_HOST_FLAGS)  \
+	$(STAGE1_FLAGS_TO_PASS)  clean
+@endif libctf-bootstrap
+
+
+.PHONY: all-stage2-libctf maybe-all-stage2-libctf
+.PHONY: clean-stage2-libctf maybe-clean-stage2-libctf
+maybe-all-stage2-libctf:
+maybe-clean-stage2-libctf:
+@if libctf-bootstrap
+maybe-all-stage2-libctf: all-stage2-libctf
+all-stage2: all-stage2-libctf
+TARGET-stage2-libctf = $(TARGET-libctf)
+all-stage2-libctf: configure-stage2-libctf
+	@[ $(current_stage) = stage2 ] || $(MAKE) stage2-start
+	@r=`${PWD_COMMAND}`; export r; \
+	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+	TFLAGS="$(STAGE2_TFLAGS)"; \
+	$(HOST_EXPORTS) \
+	$(POSTSTAGE1_HOST_EXPORTS)  \
+	cd $(HOST_SUBDIR)/libctf && \
+	 \
+	$(MAKE) $(BASE_FLAGS_TO_PASS) \
+		CFLAGS="$(STAGE2_CFLAGS)" \
+		CXXFLAGS="$(STAGE2_CXXFLAGS)" \
+		LIBCFLAGS="$(STAGE2_CFLAGS)" \
+		CFLAGS_FOR_TARGET="$(CFLAGS_FOR_TARGET)" \
+		CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" \
+		LIBCFLAGS_FOR_TARGET="$(LIBCFLAGS_FOR_TARGET)" \
+		$(EXTRA_HOST_FLAGS) $(POSTSTAGE1_FLAGS_TO_PASS)  \
+		TFLAGS="$(STAGE2_TFLAGS)"  \
+		$(TARGET-stage2-libctf)
+
+maybe-clean-stage2-libctf: clean-stage2-libctf
+clean-stage2: clean-stage2-libctf
+clean-stage2-libctf:
+	@if [ $(current_stage) = stage2 ]; then \
+	  [ -f $(HOST_SUBDIR)/libctf/Makefile ] || exit 0; \
+	else \
+	  [ -f $(HOST_SUBDIR)/stage2-libctf/Makefile ] || exit 0; \
+	  $(MAKE) stage2-start; \
+	fi; \
+	cd $(HOST_SUBDIR)/libctf && \
+	$(MAKE) $(EXTRA_HOST_FLAGS) $(POSTSTAGE1_FLAGS_TO_PASS)  clean
+@endif libctf-bootstrap
+
+
+.PHONY: all-stage3-libctf maybe-all-stage3-libctf
+.PHONY: clean-stage3-libctf maybe-clean-stage3-libctf
+maybe-all-stage3-libctf:
+maybe-clean-stage3-libctf:
+@if libctf-bootstrap
+maybe-all-stage3-libctf: all-stage3-libctf
+all-stage3: all-stage3-libctf
+TARGET-stage3-libctf = $(TARGET-libctf)
+all-stage3-libctf: configure-stage3-libctf
+	@[ $(current_stage) = stage3 ] || $(MAKE) stage3-start
+	@r=`${PWD_COMMAND}`; export r; \
+	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+	TFLAGS="$(STAGE3_TFLAGS)"; \
+	$(HOST_EXPORTS) \
+	$(POSTSTAGE1_HOST_EXPORTS)  \
+	cd $(HOST_SUBDIR)/libctf && \
+	 \
+	$(MAKE) $(BASE_FLAGS_TO_PASS) \
+		CFLAGS="$(STAGE3_CFLAGS)" \
+		CXXFLAGS="$(STAGE3_CXXFLAGS)" \
+		LIBCFLAGS="$(STAGE3_CFLAGS)" \
+		CFLAGS_FOR_TARGET="$(CFLAGS_FOR_TARGET)" \
+		CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" \
+		LIBCFLAGS_FOR_TARGET="$(LIBCFLAGS_FOR_TARGET)" \
+		$(EXTRA_HOST_FLAGS) $(POSTSTAGE1_FLAGS_TO_PASS)  \
+		TFLAGS="$(STAGE3_TFLAGS)"  \
+		$(TARGET-stage3-libctf)
+
+maybe-clean-stage3-libctf: clean-stage3-libctf
+clean-stage3: clean-stage3-libctf
+clean-stage3-libctf:
+	@if [ $(current_stage) = stage3 ]; then \
+	  [ -f $(HOST_SUBDIR)/libctf/Makefile ] || exit 0; \
+	else \
+	  [ -f $(HOST_SUBDIR)/stage3-libctf/Makefile ] || exit 0; \
+	  $(MAKE) stage3-start; \
+	fi; \
+	cd $(HOST_SUBDIR)/libctf && \
+	$(MAKE) $(EXTRA_HOST_FLAGS) $(POSTSTAGE1_FLAGS_TO_PASS)  clean
+@endif libctf-bootstrap
+
+
+.PHONY: all-stage4-libctf maybe-all-stage4-libctf
+.PHONY: clean-stage4-libctf maybe-clean-stage4-libctf
+maybe-all-stage4-libctf:
+maybe-clean-stage4-libctf:
+@if libctf-bootstrap
+maybe-all-stage4-libctf: all-stage4-libctf
+all-stage4: all-stage4-libctf
+TARGET-stage4-libctf = $(TARGET-libctf)
+all-stage4-libctf: configure-stage4-libctf
+	@[ $(current_stage) = stage4 ] || $(MAKE) stage4-start
+	@r=`${PWD_COMMAND}`; export r; \
+	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+	TFLAGS="$(STAGE4_TFLAGS)"; \
+	$(HOST_EXPORTS) \
+	$(POSTSTAGE1_HOST_EXPORTS)  \
+	cd $(HOST_SUBDIR)/libctf && \
+	 \
+	$(MAKE) $(BASE_FLAGS_TO_PASS) \
+		CFLAGS="$(STAGE4_CFLAGS)" \
+		CXXFLAGS="$(STAGE4_CXXFLAGS)" \
+		LIBCFLAGS="$(STAGE4_CFLAGS)" \
+		CFLAGS_FOR_TARGET="$(CFLAGS_FOR_TARGET)" \
+		CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" \
+		LIBCFLAGS_FOR_TARGET="$(LIBCFLAGS_FOR_TARGET)" \
+		$(EXTRA_HOST_FLAGS) $(POSTSTAGE1_FLAGS_TO_PASS)  \
+		TFLAGS="$(STAGE4_TFLAGS)"  \
+		$(TARGET-stage4-libctf)
+
+maybe-clean-stage4-libctf: clean-stage4-libctf
+clean-stage4: clean-stage4-libctf
+clean-stage4-libctf:
+	@if [ $(current_stage) = stage4 ]; then \
+	  [ -f $(HOST_SUBDIR)/libctf/Makefile ] || exit 0; \
+	else \
+	  [ -f $(HOST_SUBDIR)/stage4-libctf/Makefile ] || exit 0; \
+	  $(MAKE) stage4-start; \
+	fi; \
+	cd $(HOST_SUBDIR)/libctf && \
+	$(MAKE) $(EXTRA_HOST_FLAGS) $(POSTSTAGE1_FLAGS_TO_PASS)  clean
+@endif libctf-bootstrap
+
+
+.PHONY: all-stageprofile-libctf maybe-all-stageprofile-libctf
+.PHONY: clean-stageprofile-libctf maybe-clean-stageprofile-libctf
+maybe-all-stageprofile-libctf:
+maybe-clean-stageprofile-libctf:
+@if libctf-bootstrap
+maybe-all-stageprofile-libctf: all-stageprofile-libctf
+all-stageprofile: all-stageprofile-libctf
+TARGET-stageprofile-libctf = $(TARGET-libctf)
+all-stageprofile-libctf: configure-stageprofile-libctf
+	@[ $(current_stage) = stageprofile ] || $(MAKE) stageprofile-start
+	@r=`${PWD_COMMAND}`; export r; \
+	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+	TFLAGS="$(STAGEprofile_TFLAGS)"; \
+	$(HOST_EXPORTS) \
+	$(POSTSTAGE1_HOST_EXPORTS)  \
+	cd $(HOST_SUBDIR)/libctf && \
+	 \
+	$(MAKE) $(BASE_FLAGS_TO_PASS) \
+		CFLAGS="$(STAGEprofile_CFLAGS)" \
+		CXXFLAGS="$(STAGEprofile_CXXFLAGS)" \
+		LIBCFLAGS="$(STAGEprofile_CFLAGS)" \
+		CFLAGS_FOR_TARGET="$(CFLAGS_FOR_TARGET)" \
+		CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" \
+		LIBCFLAGS_FOR_TARGET="$(LIBCFLAGS_FOR_TARGET)" \
+		$(EXTRA_HOST_FLAGS) $(POSTSTAGE1_FLAGS_TO_PASS)  \
+		TFLAGS="$(STAGEprofile_TFLAGS)"  \
+		$(TARGET-stageprofile-libctf)
+
+maybe-clean-stageprofile-libctf: clean-stageprofile-libctf
+clean-stageprofile: clean-stageprofile-libctf
+clean-stageprofile-libctf:
+	@if [ $(current_stage) = stageprofile ]; then \
+	  [ -f $(HOST_SUBDIR)/libctf/Makefile ] || exit 0; \
+	else \
+	  [ -f $(HOST_SUBDIR)/stageprofile-libctf/Makefile ] || exit 0; \
+	  $(MAKE) stageprofile-start; \
+	fi; \
+	cd $(HOST_SUBDIR)/libctf && \
+	$(MAKE) $(EXTRA_HOST_FLAGS) $(POSTSTAGE1_FLAGS_TO_PASS)  clean
+@endif libctf-bootstrap
+
+
+.PHONY: all-stagefeedback-libctf maybe-all-stagefeedback-libctf
+.PHONY: clean-stagefeedback-libctf maybe-clean-stagefeedback-libctf
+maybe-all-stagefeedback-libctf:
+maybe-clean-stagefeedback-libctf:
+@if libctf-bootstrap
+maybe-all-stagefeedback-libctf: all-stagefeedback-libctf
+all-stagefeedback: all-stagefeedback-libctf
+TARGET-stagefeedback-libctf = $(TARGET-libctf)
+all-stagefeedback-libctf: configure-stagefeedback-libctf
+	@[ $(current_stage) = stagefeedback ] || $(MAKE) stagefeedback-start
+	@r=`${PWD_COMMAND}`; export r; \
+	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+	TFLAGS="$(STAGEfeedback_TFLAGS)"; \
+	$(HOST_EXPORTS) \
+	$(POSTSTAGE1_HOST_EXPORTS)  \
+	cd $(HOST_SUBDIR)/libctf && \
+	 \
+	$(MAKE) $(BASE_FLAGS_TO_PASS) \
+		CFLAGS="$(STAGEfeedback_CFLAGS)" \
+		CXXFLAGS="$(STAGEfeedback_CXXFLAGS)" \
+		LIBCFLAGS="$(STAGEfeedback_CFLAGS)" \
+		CFLAGS_FOR_TARGET="$(CFLAGS_FOR_TARGET)" \
+		CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" \
+		LIBCFLAGS_FOR_TARGET="$(LIBCFLAGS_FOR_TARGET)" \
+		$(EXTRA_HOST_FLAGS) $(POSTSTAGE1_FLAGS_TO_PASS)  \
+		TFLAGS="$(STAGEfeedback_TFLAGS)"  \
+		$(TARGET-stagefeedback-libctf)
+
+maybe-clean-stagefeedback-libctf: clean-stagefeedback-libctf
+clean-stagefeedback: clean-stagefeedback-libctf
+clean-stagefeedback-libctf:
+	@if [ $(current_stage) = stagefeedback ]; then \
+	  [ -f $(HOST_SUBDIR)/libctf/Makefile ] || exit 0; \
+	else \
+	  [ -f $(HOST_SUBDIR)/stagefeedback-libctf/Makefile ] || exit 0; \
+	  $(MAKE) stagefeedback-start; \
+	fi; \
+	cd $(HOST_SUBDIR)/libctf && \
+	$(MAKE) $(EXTRA_HOST_FLAGS) $(POSTSTAGE1_FLAGS_TO_PASS)  clean
+@endif libctf-bootstrap
+
+
+
+
+
+.PHONY: check-libctf maybe-check-libctf
+maybe-check-libctf:
+@if libctf
+maybe-check-libctf: check-libctf
+
+check-libctf:
+
+@endif libctf
+
+.PHONY: install-libctf maybe-install-libctf
+maybe-install-libctf:
+@if libctf
+maybe-install-libctf: install-libctf
+
+install-libctf:
+
+@endif libctf
+
+.PHONY: install-strip-libctf maybe-install-strip-libctf
+maybe-install-strip-libctf:
+@if libctf
+maybe-install-strip-libctf: install-strip-libctf
+
+install-strip-libctf:
+
+@endif libctf
+
+# Other targets (info, dvi, pdf, etc.)
+
+.PHONY: maybe-info-libctf info-libctf
+maybe-info-libctf:
+@if libctf
+maybe-info-libctf: info-libctf
+
+info-libctf: \
+    configure-libctf 
+	@[ -f ./libctf/Makefile ] || exit 0; \
+	r=`${PWD_COMMAND}`; export r; \
+	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+	$(HOST_EXPORTS) \
+	for flag in $(EXTRA_HOST_FLAGS) ; do \
+	  eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+	done; \
+	echo "Doing info in libctf"; \
+	(cd $(HOST_SUBDIR)/libctf && \
+	  $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+	          "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+	          "RANLIB=$${RANLIB}" \
+	          "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+	          info) \
+	  || exit 1
+
+@endif libctf
+
+.PHONY: maybe-dvi-libctf dvi-libctf
+maybe-dvi-libctf:
+@if libctf
+maybe-dvi-libctf: dvi-libctf
+
+dvi-libctf: \
+    configure-libctf 
+	@[ -f ./libctf/Makefile ] || exit 0; \
+	r=`${PWD_COMMAND}`; export r; \
+	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+	$(HOST_EXPORTS) \
+	for flag in $(EXTRA_HOST_FLAGS) ; do \
+	  eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+	done; \
+	echo "Doing dvi in libctf"; \
+	(cd $(HOST_SUBDIR)/libctf && \
+	  $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+	          "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+	          "RANLIB=$${RANLIB}" \
+	          "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+	          dvi) \
+	  || exit 1
+
+@endif libctf
+
+.PHONY: maybe-pdf-libctf pdf-libctf
+maybe-pdf-libctf:
+@if libctf
+maybe-pdf-libctf: pdf-libctf
+
+pdf-libctf: \
+    configure-libctf 
+	@[ -f ./libctf/Makefile ] || exit 0; \
+	r=`${PWD_COMMAND}`; export r; \
+	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+	$(HOST_EXPORTS) \
+	for flag in $(EXTRA_HOST_FLAGS) ; do \
+	  eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+	done; \
+	echo "Doing pdf in libctf"; \
+	(cd $(HOST_SUBDIR)/libctf && \
+	  $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+	          "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+	          "RANLIB=$${RANLIB}" \
+	          "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+	          pdf) \
+	  || exit 1
+
+@endif libctf
+
+.PHONY: maybe-html-libctf html-libctf
+maybe-html-libctf:
+@if libctf
+maybe-html-libctf: html-libctf
+
+html-libctf: \
+    configure-libctf 
+	@[ -f ./libctf/Makefile ] || exit 0; \
+	r=`${PWD_COMMAND}`; export r; \
+	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+	$(HOST_EXPORTS) \
+	for flag in $(EXTRA_HOST_FLAGS) ; do \
+	  eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+	done; \
+	echo "Doing html in libctf"; \
+	(cd $(HOST_SUBDIR)/libctf && \
+	  $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+	          "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+	          "RANLIB=$${RANLIB}" \
+	          "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+	          html) \
+	  || exit 1
+
+@endif libctf
+
+.PHONY: maybe-TAGS-libctf TAGS-libctf
+maybe-TAGS-libctf:
+@if libctf
+maybe-TAGS-libctf: TAGS-libctf
+
+TAGS-libctf: \
+    configure-libctf 
+	@[ -f ./libctf/Makefile ] || exit 0; \
+	r=`${PWD_COMMAND}`; export r; \
+	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+	$(HOST_EXPORTS) \
+	for flag in $(EXTRA_HOST_FLAGS) ; do \
+	  eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+	done; \
+	echo "Doing TAGS in libctf"; \
+	(cd $(HOST_SUBDIR)/libctf && \
+	  $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+	          "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+	          "RANLIB=$${RANLIB}" \
+	          "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+	          TAGS) \
+	  || exit 1
+
+@endif libctf
+
+.PHONY: maybe-install-info-libctf install-info-libctf
+maybe-install-info-libctf:
+@if libctf
+maybe-install-info-libctf: install-info-libctf
+
+install-info-libctf: \
+    configure-libctf \
+    info-libctf 
+	@[ -f ./libctf/Makefile ] || exit 0; \
+	r=`${PWD_COMMAND}`; export r; \
+	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+	$(HOST_EXPORTS) \
+	for flag in $(EXTRA_HOST_FLAGS) ; do \
+	  eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+	done; \
+	echo "Doing install-info in libctf"; \
+	(cd $(HOST_SUBDIR)/libctf && \
+	  $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+	          "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+	          "RANLIB=$${RANLIB}" \
+	          "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+	          install-info) \
+	  || exit 1
+
+@endif libctf
+
+.PHONY: maybe-install-pdf-libctf install-pdf-libctf
+maybe-install-pdf-libctf:
+@if libctf
+maybe-install-pdf-libctf: install-pdf-libctf
+
+install-pdf-libctf: \
+    configure-libctf \
+    pdf-libctf 
+	@[ -f ./libctf/Makefile ] || exit 0; \
+	r=`${PWD_COMMAND}`; export r; \
+	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+	$(HOST_EXPORTS) \
+	for flag in $(EXTRA_HOST_FLAGS) ; do \
+	  eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+	done; \
+	echo "Doing install-pdf in libctf"; \
+	(cd $(HOST_SUBDIR)/libctf && \
+	  $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+	          "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+	          "RANLIB=$${RANLIB}" \
+	          "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+	          install-pdf) \
+	  || exit 1
+
+@endif libctf
+
+.PHONY: maybe-install-html-libctf install-html-libctf
+maybe-install-html-libctf:
+@if libctf
+maybe-install-html-libctf: install-html-libctf
+
+install-html-libctf: \
+    configure-libctf \
+    html-libctf 
+	@[ -f ./libctf/Makefile ] || exit 0; \
+	r=`${PWD_COMMAND}`; export r; \
+	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+	$(HOST_EXPORTS) \
+	for flag in $(EXTRA_HOST_FLAGS) ; do \
+	  eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+	done; \
+	echo "Doing install-html in libctf"; \
+	(cd $(HOST_SUBDIR)/libctf && \
+	  $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+	          "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+	          "RANLIB=$${RANLIB}" \
+	          "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+	          install-html) \
+	  || exit 1
+
+@endif libctf
+
+.PHONY: maybe-installcheck-libctf installcheck-libctf
+maybe-installcheck-libctf:
+@if libctf
+maybe-installcheck-libctf: installcheck-libctf
+
+installcheck-libctf: \
+    configure-libctf 
+	@[ -f ./libctf/Makefile ] || exit 0; \
+	r=`${PWD_COMMAND}`; export r; \
+	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+	$(HOST_EXPORTS) \
+	for flag in $(EXTRA_HOST_FLAGS) ; do \
+	  eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+	done; \
+	echo "Doing installcheck in libctf"; \
+	(cd $(HOST_SUBDIR)/libctf && \
+	  $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+	          "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+	          "RANLIB=$${RANLIB}" \
+	          "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+	          installcheck) \
+	  || exit 1
+
+@endif libctf
+
+.PHONY: maybe-mostlyclean-libctf mostlyclean-libctf
+maybe-mostlyclean-libctf:
+@if libctf
+maybe-mostlyclean-libctf: mostlyclean-libctf
+
+mostlyclean-libctf: 
+	@[ -f ./libctf/Makefile ] || exit 0; \
+	r=`${PWD_COMMAND}`; export r; \
+	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+	$(HOST_EXPORTS) \
+	for flag in $(EXTRA_HOST_FLAGS) ; do \
+	  eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+	done; \
+	echo "Doing mostlyclean in libctf"; \
+	(cd $(HOST_SUBDIR)/libctf && \
+	  $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+	          "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+	          "RANLIB=$${RANLIB}" \
+	          "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+	          mostlyclean) \
+	  || exit 1
+
+@endif libctf
+
+.PHONY: maybe-clean-libctf clean-libctf
+maybe-clean-libctf:
+@if libctf
+maybe-clean-libctf: clean-libctf
+
+clean-libctf: 
+	@[ -f ./libctf/Makefile ] || exit 0; \
+	r=`${PWD_COMMAND}`; export r; \
+	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+	$(HOST_EXPORTS) \
+	for flag in $(EXTRA_HOST_FLAGS) ; do \
+	  eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+	done; \
+	echo "Doing clean in libctf"; \
+	(cd $(HOST_SUBDIR)/libctf && \
+	  $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+	          "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+	          "RANLIB=$${RANLIB}" \
+	          "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+	          clean) \
+	  || exit 1
+
+@endif libctf
+
+.PHONY: maybe-distclean-libctf distclean-libctf
+maybe-distclean-libctf:
+@if libctf
+maybe-distclean-libctf: distclean-libctf
+
+distclean-libctf: 
+	@[ -f ./libctf/Makefile ] || exit 0; \
+	r=`${PWD_COMMAND}`; export r; \
+	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+	$(HOST_EXPORTS) \
+	for flag in $(EXTRA_HOST_FLAGS) ; do \
+	  eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+	done; \
+	echo "Doing distclean in libctf"; \
+	(cd $(HOST_SUBDIR)/libctf && \
+	  $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+	          "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+	          "RANLIB=$${RANLIB}" \
+	          "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+	          distclean) \
+	  || exit 1
+
+@endif libctf
+
+.PHONY: maybe-maintainer-clean-libctf maintainer-clean-libctf
+maybe-maintainer-clean-libctf:
+@if libctf
+maybe-maintainer-clean-libctf: maintainer-clean-libctf
+
+maintainer-clean-libctf: 
+	@[ -f ./libctf/Makefile ] || exit 0; \
+	r=`${PWD_COMMAND}`; export r; \
+	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+	$(HOST_EXPORTS) \
+	for flag in $(EXTRA_HOST_FLAGS) ; do \
+	  eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+	done; \
+	echo "Doing maintainer-clean in libctf"; \
+	(cd $(HOST_SUBDIR)/libctf && \
+	  $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+	          "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+	          "RANLIB=$${RANLIB}" \
+	          "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+	          maintainer-clean) \
+	  || exit 1
+
+@endif libctf
+
+
+
 # ---------------------------------------
 # Modules which run on the target machine
 # ---------------------------------------
@@ -47179,6 +48062,11 @@ stage1-start::
 	  mkdir stage1-lto-plugin; \
 	mv stage1-lto-plugin lto-plugin
 @endif lto-plugin
+@if libctf
+	@cd $(HOST_SUBDIR); [ -d stage1-libctf ] || \
+	  mkdir stage1-libctf; \
+	mv stage1-libctf libctf
+@endif libctf
 	@[ -d stage1-$(TARGET_SUBDIR) ] || \
 	  mkdir stage1-$(TARGET_SUBDIR); \
 	mv stage1-$(TARGET_SUBDIR) $(TARGET_SUBDIR)
@@ -47294,6 +48182,11 @@ stage1-end::
 	  cd $(HOST_SUBDIR); mv lto-plugin stage1-lto-plugin; \
 	fi
 @endif lto-plugin
+@if libctf
+	@if test -d $(HOST_SUBDIR)/libctf; then \
+	  cd $(HOST_SUBDIR); mv libctf stage1-libctf; \
+	fi
+@endif libctf
 	@if test -d $(TARGET_SUBDIR); then \
 	  mv $(TARGET_SUBDIR) stage1-$(TARGET_SUBDIR); \
 	fi
@@ -47474,6 +48367,12 @@ stage2-start::
 	mv stage2-lto-plugin lto-plugin; \
 	mv stage1-lto-plugin prev-lto-plugin || test -f stage1-lean 
 @endif lto-plugin
+@if libctf
+	@cd $(HOST_SUBDIR); [ -d stage2-libctf ] || \
+	  mkdir stage2-libctf; \
+	mv stage2-libctf libctf; \
+	mv stage1-libctf prev-libctf || test -f stage1-lean 
+@endif libctf
 	@[ -d stage2-$(TARGET_SUBDIR) ] || \
 	  mkdir stage2-$(TARGET_SUBDIR); \
 	mv stage2-$(TARGET_SUBDIR) $(TARGET_SUBDIR); \
@@ -47612,6 +48511,12 @@ stage2-end::
 	  mv prev-lto-plugin stage1-lto-plugin; : ; \
 	fi
 @endif lto-plugin
+@if libctf
+	@if test -d $(HOST_SUBDIR)/libctf; then \
+	  cd $(HOST_SUBDIR); mv libctf stage2-libctf; \
+	  mv prev-libctf stage1-libctf; : ; \
+	fi
+@endif libctf
 	@if test -d $(TARGET_SUBDIR); then \
 	  mv $(TARGET_SUBDIR) stage2-$(TARGET_SUBDIR); \
 	  mv prev-$(TARGET_SUBDIR) stage1-$(TARGET_SUBDIR); : ; \
@@ -47816,6 +48721,12 @@ stage3-start::
 	mv stage3-lto-plugin lto-plugin; \
 	mv stage2-lto-plugin prev-lto-plugin || test -f stage2-lean 
 @endif lto-plugin
+@if libctf
+	@cd $(HOST_SUBDIR); [ -d stage3-libctf ] || \
+	  mkdir stage3-libctf; \
+	mv stage3-libctf libctf; \
+	mv stage2-libctf prev-libctf || test -f stage2-lean 
+@endif libctf
 	@[ -d stage3-$(TARGET_SUBDIR) ] || \
 	  mkdir stage3-$(TARGET_SUBDIR); \
 	mv stage3-$(TARGET_SUBDIR) $(TARGET_SUBDIR); \
@@ -47954,6 +48865,12 @@ stage3-end::
 	  mv prev-lto-plugin stage2-lto-plugin; : ; \
 	fi
 @endif lto-plugin
+@if libctf
+	@if test -d $(HOST_SUBDIR)/libctf; then \
+	  cd $(HOST_SUBDIR); mv libctf stage3-libctf; \
+	  mv prev-libctf stage2-libctf; : ; \
+	fi
+@endif libctf
 	@if test -d $(TARGET_SUBDIR); then \
 	  mv $(TARGET_SUBDIR) stage3-$(TARGET_SUBDIR); \
 	  mv prev-$(TARGET_SUBDIR) stage2-$(TARGET_SUBDIR); : ; \
@@ -48214,6 +49131,12 @@ stage4-start::
 	mv stage4-lto-plugin lto-plugin; \
 	mv stage3-lto-plugin prev-lto-plugin || test -f stage3-lean 
 @endif lto-plugin
+@if libctf
+	@cd $(HOST_SUBDIR); [ -d stage4-libctf ] || \
+	  mkdir stage4-libctf; \
+	mv stage4-libctf libctf; \
+	mv stage3-libctf prev-libctf || test -f stage3-lean 
+@endif libctf
 	@[ -d stage4-$(TARGET_SUBDIR) ] || \
 	  mkdir stage4-$(TARGET_SUBDIR); \
 	mv stage4-$(TARGET_SUBDIR) $(TARGET_SUBDIR); \
@@ -48352,6 +49275,12 @@ stage4-end::
 	  mv prev-lto-plugin stage3-lto-plugin; : ; \
 	fi
 @endif lto-plugin
+@if libctf
+	@if test -d $(HOST_SUBDIR)/libctf; then \
+	  cd $(HOST_SUBDIR); mv libctf stage4-libctf; \
+	  mv prev-libctf stage3-libctf; : ; \
+	fi
+@endif libctf
 	@if test -d $(TARGET_SUBDIR); then \
 	  mv $(TARGET_SUBDIR) stage4-$(TARGET_SUBDIR); \
 	  mv prev-$(TARGET_SUBDIR) stage3-$(TARGET_SUBDIR); : ; \
@@ -48600,6 +49529,12 @@ stageprofile-start::
 	mv stageprofile-lto-plugin lto-plugin; \
 	mv stage1-lto-plugin prev-lto-plugin || test -f stage1-lean 
 @endif lto-plugin
+@if libctf
+	@cd $(HOST_SUBDIR); [ -d stageprofile-libctf ] || \
+	  mkdir stageprofile-libctf; \
+	mv stageprofile-libctf libctf; \
+	mv stage1-libctf prev-libctf || test -f stage1-lean 
+@endif libctf
 	@[ -d stageprofile-$(TARGET_SUBDIR) ] || \
 	  mkdir stageprofile-$(TARGET_SUBDIR); \
 	mv stageprofile-$(TARGET_SUBDIR) $(TARGET_SUBDIR); \
@@ -48738,6 +49673,12 @@ stageprofile-end::
 	  mv prev-lto-plugin stage1-lto-plugin; : ; \
 	fi
 @endif lto-plugin
+@if libctf
+	@if test -d $(HOST_SUBDIR)/libctf; then \
+	  cd $(HOST_SUBDIR); mv libctf stageprofile-libctf; \
+	  mv prev-libctf stage1-libctf; : ; \
+	fi
+@endif libctf
 	@if test -d $(TARGET_SUBDIR); then \
 	  mv $(TARGET_SUBDIR) stageprofile-$(TARGET_SUBDIR); \
 	  mv prev-$(TARGET_SUBDIR) stage1-$(TARGET_SUBDIR); : ; \
@@ -48919,6 +49860,12 @@ stagefeedback-start::
 	mv stagefeedback-lto-plugin lto-plugin; \
 	mv stageprofile-lto-plugin prev-lto-plugin || test -f stageprofile-lean 
 @endif lto-plugin
+@if libctf
+	@cd $(HOST_SUBDIR); [ -d stagefeedback-libctf ] || \
+	  mkdir stagefeedback-libctf; \
+	mv stagefeedback-libctf libctf; \
+	mv stageprofile-libctf prev-libctf || test -f stageprofile-lean 
+@endif libctf
 	@[ -d stagefeedback-$(TARGET_SUBDIR) ] || \
 	  mkdir stagefeedback-$(TARGET_SUBDIR); \
 	mv stagefeedback-$(TARGET_SUBDIR) $(TARGET_SUBDIR); \
@@ -49057,6 +50004,12 @@ stagefeedback-end::
 	  mv prev-lto-plugin stageprofile-lto-plugin; : ; \
 	fi
 @endif lto-plugin
+@if libctf
+	@if test -d $(HOST_SUBDIR)/libctf; then \
+	  cd $(HOST_SUBDIR); mv libctf stagefeedback-libctf; \
+	  mv prev-libctf stageprofile-libctf; : ; \
+	fi
+@endif libctf
 	@if test -d $(TARGET_SUBDIR); then \
 	  mv $(TARGET_SUBDIR) stagefeedback-$(TARGET_SUBDIR); \
 	  mv prev-$(TARGET_SUBDIR) stageprofile-$(TARGET_SUBDIR); : ; \
@@ -49737,6 +50690,13 @@ all-stage3-binutils: maybe-all-stage3-gas
 all-stage4-binutils: maybe-all-stage4-gas
 all-stageprofile-binutils: maybe-all-stageprofile-gas
 all-stagefeedback-binutils: maybe-all-stagefeedback-gas
+all-binutils: maybe-all-libctf
+all-stage1-binutils: maybe-all-stage1-libctf
+all-stage2-binutils: maybe-all-stage2-libctf
+all-stage3-binutils: maybe-all-stage3-libctf
+all-stage4-binutils: maybe-all-stage4-libctf
+all-stageprofile-binutils: maybe-all-stageprofile-libctf
+all-stagefeedback-binutils: maybe-all-stagefeedback-libctf
 install-binutils: maybe-install-opcodes
 install-strip-binutils: maybe-install-strip-opcodes
 install-opcodes: maybe-install-bfd
@@ -49949,6 +50909,27 @@ install-strip-sid: maybe-install-strip-tk
 all-sim: maybe-all-readline
 all-sim: maybe-configure-gdb
 all-fastjar: maybe-all-build-texinfo
+all-libctf: all-libiberty
+all-stage1-libctf: all-stage1-libiberty
+all-stage2-libctf: all-stage2-libiberty
+all-stage3-libctf: all-stage3-libiberty
+all-stage4-libctf: all-stage4-libiberty
+all-stageprofile-libctf: all-stageprofile-libiberty
+all-stagefeedback-libctf: all-stagefeedback-libiberty
+all-libctf: maybe-all-bfd
+all-stage1-libctf: maybe-all-stage1-bfd
+all-stage2-libctf: maybe-all-stage2-bfd
+all-stage3-libctf: maybe-all-stage3-bfd
+all-stage4-libctf: maybe-all-stage4-bfd
+all-stageprofile-libctf: maybe-all-stageprofile-bfd
+all-stagefeedback-libctf: maybe-all-stagefeedback-bfd
+all-libctf: maybe-all-zlib
+all-stage1-libctf: maybe-all-stage1-zlib
+all-stage2-libctf: maybe-all-stage2-zlib
+all-stage3-libctf: maybe-all-stage3-zlib
+all-stage4-libctf: maybe-all-stage4-zlib
+all-stageprofile-libctf: maybe-all-stageprofile-zlib
+all-stagefeedback-libctf: maybe-all-stagefeedback-zlib
 all-bison: maybe-all-build-texinfo
 all-flex: maybe-all-build-bison
 all-flex: maybe-all-m4
diff --git a/configure b/configure
index 3747645961..3e95ce50ff 100755
--- a/configure
+++ b/configure
@@ -2769,7 +2769,7 @@ build_tools="build-texinfo build-flex build-bison build-m4 build-fixincludes"
 
 # these libraries are used by various programs built for the host environment
 #f
-host_libs="intl libiberty opcodes bfd readline tcl tk itcl libgui zlib libbacktrace libcpp libdecnumber gmp mpfr mpc isl libelf libiconv"
+host_libs="intl libiberty opcodes bfd readline tcl tk itcl libgui zlib libbacktrace libcpp libdecnumber gmp mpfr mpc isl libelf libiconv libctf"
 
 # these tools are built for the host environment
 # Note, the powerpc-eabi build depends on sim occurring before gdb in order to
diff --git a/configure.ac b/configure.ac
index 46501c2882..c84263c516 100644
--- a/configure.ac
+++ b/configure.ac
@@ -131,7 +131,7 @@ build_tools="build-texinfo build-flex build-bison build-m4 build-fixincludes"
 
 # these libraries are used by various programs built for the host environment
 #f
-host_libs="intl libiberty opcodes bfd readline tcl tk itcl libgui zlib libbacktrace libcpp libdecnumber gmp mpfr mpc isl libelf libiconv"
+host_libs="intl libiberty opcodes bfd readline tcl tk itcl libgui zlib libbacktrace libcpp libdecnumber gmp mpfr mpc isl libelf libiconv libctf"
 
 # these tools are built for the host environment
 # Note, the powerpc-eabi build depends on sim occurring before gdb in order to
diff --git a/libctf/Makefile.am b/libctf/Makefile.am
new file mode 100644
index 0000000000..5fe2c95901
--- /dev/null
+++ b/libctf/Makefile.am
@@ -0,0 +1,31 @@
+## Process this file with automake to produce Makefile.in.
+#
+#   Copyright (C) 2019 Free Software Foundation, Inc.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; see the file COPYING.  If not see
+# <http://www.gnu.org/licenses/>.
+#
+
+ACLOCAL_AMFLAGS = -I .. -I ../config
+
+AUTOMAKE_OPTIONS = foreign no-texinfo.tex
+
+AM_CPPFLAGS = -D_GNU_SOURCE -I$(top_srcdir) -I$(top_srcdir)/../include -I$(top_srcdir)/../bfd -I../bfd
+AM_CFLAGS = -std=gnu99 @ac_libctf_warn_cflags@ @warn@ @c_warn@ @WARN_PEDANTIC@ @WERROR@
+
+noinst_LIBRARIES = libctf.a
+
+libctf_a_SOURCES = ctf-archive.c ctf-dump.c ctf-create.c ctf-decl.c ctf-error.c \
+		   ctf-hash.c ctf-labels.c ctf-lookup.c ctf-open.c ctf-open-bfd.c \
+		   ctf-subr.c ctf-types.c ctf-util.c
diff --git a/libctf/Makefile.in b/libctf/Makefile.in
new file mode 100644
index 0000000000..b0afa5b80d
--- /dev/null
+++ b/libctf/Makefile.in
@@ -0,0 +1,767 @@
+# Makefile.in generated by automake 1.15.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2017 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+#   Copyright (C) 2019 Free Software Foundation, Inc.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; see the file COPYING.  If not see
+# <http://www.gnu.org/licenses/>.
+#
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+  if test -z '$(MAKELEVEL)'; then \
+    false; \
+  elif test -n '$(MAKE_HOST)'; then \
+    true; \
+  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+    true; \
+  else \
+    false; \
+  fi; \
+}
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+subdir = .
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \
+	$(top_srcdir)/../config/lead-dot.m4 \
+	$(top_srcdir)/../config/override.m4 \
+	$(top_srcdir)/../config/warnings.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
+	$(am__configure_deps) $(am__DIST_COMMON)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+ARFLAGS = cru
+AM_V_AR = $(am__v_AR_@AM_V@)
+am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@)
+am__v_AR_0 = @echo "  AR      " $@;
+am__v_AR_1 = 
+libctf_a_AR = $(AR) $(ARFLAGS)
+libctf_a_LIBADD =
+am_libctf_a_OBJECTS = ctf-archive.$(OBJEXT) ctf-dump.$(OBJEXT) \
+	ctf-create.$(OBJEXT) ctf-decl.$(OBJEXT) ctf-error.$(OBJEXT) \
+	ctf-hash.$(OBJEXT) ctf-labels.$(OBJEXT) ctf-lookup.$(OBJEXT) \
+	ctf-open.$(OBJEXT) ctf-open-bfd.$(OBJEXT) ctf-subr.$(OBJEXT) \
+	ctf-types.$(OBJEXT) ctf-util.$(OBJEXT)
+libctf_a_OBJECTS = $(am_libctf_a_OBJECTS)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/../depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo "  CC      " $@;
+am__v_CC_1 = 
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo "  CCLD    " $@;
+am__v_CCLD_1 = 
+SOURCES = $(libctf_a_SOURCES)
+DIST_SOURCES = $(libctf_a_SOURCES)
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \
+	$(LISP)config.h.in
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+CSCOPE = cscope
+AM_RECURSIVE_TARGETS = cscope
+am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \
+	$(top_srcdir)/../ar-lib $(top_srcdir)/../compile \
+	$(top_srcdir)/../depcomp $(top_srcdir)/../install-sh \
+	$(top_srcdir)/../missing $(top_srcdir)/../mkinstalldirs
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+  if test -d "$(distdir)"; then \
+    find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
+      && rm -rf "$(distdir)" \
+      || { sleep 5 && rm -rf "$(distdir)"; }; \
+  else :; fi
+am__post_remove_distdir = $(am__remove_distdir)
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+DIST_TARGETS = dist-gzip
+distuninstallcheck_listfiles = find . -type f -print
+am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
+  | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+WARN_PEDANTIC = @WARN_PEDANTIC@
+WERROR = @WERROR@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_libctf_warn_cflags = @ac_libctf_warn_cflags@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build_alias = @build_alias@
+builddir = @builddir@
+c_warn = @c_warn@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host_alias = @host_alias@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+warn = @warn@
+ACLOCAL_AMFLAGS = -I .. -I ../config
+AUTOMAKE_OPTIONS = foreign no-texinfo.tex
+AM_CPPFLAGS = -D_GNU_SOURCE -I$(top_srcdir) -I$(top_srcdir)/../include -I$(top_srcdir)/../bfd -I../bfd
+AM_CFLAGS = -std=gnu99 @ac_libctf_warn_cflags@ @warn@ @c_warn@ @WARN_PEDANTIC@ @WERROR@
+noinst_LIBRARIES = libctf.a
+libctf_a_SOURCES = ctf-archive.c ctf-dump.c ctf-create.c ctf-decl.c ctf-error.c \
+		   ctf-hash.c ctf-labels.c ctf-lookup.c ctf-open.c ctf-open-bfd.c \
+		   ctf-subr.c ctf-types.c ctf-util.c
+
+all: config.h
+	$(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+am--refresh: Makefile
+	@:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
+	      $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    echo ' $(SHELL) ./config.status'; \
+	    $(SHELL) ./config.status;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	$(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	$(am__cd) $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+$(am__aclocal_m4_deps):
+
+config.h: stamp-h1
+	@test -f $@ || rm -f stamp-h1
+	@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+	@rm -f stamp-h1
+	cd $(top_builddir) && $(SHELL) ./config.status config.h
+$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) 
+	($(am__cd) $(top_srcdir) && $(AUTOHEADER))
+	rm -f stamp-h1
+	touch $@
+
+distclean-hdr:
+	-rm -f config.h stamp-h1
+
+clean-noinstLIBRARIES:
+	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+libctf.a: $(libctf_a_OBJECTS) $(libctf_a_DEPENDENCIES) $(EXTRA_libctf_a_DEPENDENCIES) 
+	$(AM_V_at)-rm -f libctf.a
+	$(AM_V_AR)$(libctf_a_AR) libctf.a $(libctf_a_OBJECTS) $(libctf_a_LIBADD)
+	$(AM_V_at)$(RANLIB) libctf.a
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctf-archive.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctf-create.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctf-decl.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctf-dump.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctf-error.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctf-hash.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctf-labels.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctf-lookup.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctf-open-bfd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctf-open.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctf-subr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctf-types.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctf-util.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+ID: $(am__tagged_files)
+	$(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	set x; \
+	here=`pwd`; \
+	$(am__define_uniq_tagged_files); \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	$(am__define_uniq_tagged_files); \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+cscope: cscope.files
+	test ! -s cscope.files \
+	  || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)
+clean-cscope:
+	-rm -f cscope.files
+cscope.files: clean-cscope cscopelist
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+	list='$(am__tagged_files)'; \
+	case "$(srcdir)" in \
+	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+	  *) sdir=$(subdir)/$(srcdir) ;; \
+	esac; \
+	for i in $$list; do \
+	  if test -f "$$i"; then \
+	    echo "$(subdir)/$$i"; \
+	  else \
+	    echo "$$sdir/$$i"; \
+	  fi; \
+	done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+	-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
+
+distdir: $(DISTFILES)
+	$(am__remove_distdir)
+	test -d "$(distdir)" || mkdir "$(distdir)"
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+	-test -n "$(am__skip_mode_fix)" \
+	|| find "$(distdir)" -type d ! -perm -755 \
+		-exec chmod u+rwx,go+rx {} \; -o \
+	  ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+	  ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+	  ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
+	|| chmod -R a+r "$(distdir)"
+dist-gzip: distdir
+	tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz
+	$(am__post_remove_distdir)
+
+dist-bzip2: distdir
+	tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2
+	$(am__post_remove_distdir)
+
+dist-lzip: distdir
+	tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz
+	$(am__post_remove_distdir)
+
+dist-xz: distdir
+	tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
+	$(am__post_remove_distdir)
+
+dist-tarZ: distdir
+	@echo WARNING: "Support for distribution archives compressed with" \
+		       "legacy program 'compress' is deprecated." >&2
+	@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
+	tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+	$(am__post_remove_distdir)
+
+dist-shar: distdir
+	@echo WARNING: "Support for shar distribution archives is" \
+	               "deprecated." >&2
+	@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
+	shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz
+	$(am__post_remove_distdir)
+
+dist-zip: distdir
+	-rm -f $(distdir).zip
+	zip -rq $(distdir).zip $(distdir)
+	$(am__post_remove_distdir)
+
+dist dist-all:
+	$(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:'
+	$(am__post_remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration.  Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+	case '$(DIST_ARCHIVES)' in \
+	*.tar.gz*) \
+	  eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\
+	*.tar.bz2*) \
+	  bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
+	*.tar.lz*) \
+	  lzip -dc $(distdir).tar.lz | $(am__untar) ;;\
+	*.tar.xz*) \
+	  xz -dc $(distdir).tar.xz | $(am__untar) ;;\
+	*.tar.Z*) \
+	  uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+	*.shar.gz*) \
+	  eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\
+	*.zip*) \
+	  unzip $(distdir).zip ;;\
+	esac
+	chmod -R a-w $(distdir)
+	chmod u+w $(distdir)
+	mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst
+	chmod a-w $(distdir)
+	test -d $(distdir)/_build || exit 0; \
+	dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+	  && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+	  && am__cwd=`pwd` \
+	  && $(am__cd) $(distdir)/_build/sub \
+	  && ../../configure \
+	    $(AM_DISTCHECK_CONFIGURE_FLAGS) \
+	    $(DISTCHECK_CONFIGURE_FLAGS) \
+	    --srcdir=../.. --prefix="$$dc_install_base" \
+	  && $(MAKE) $(AM_MAKEFLAGS) \
+	  && $(MAKE) $(AM_MAKEFLAGS) dvi \
+	  && $(MAKE) $(AM_MAKEFLAGS) check \
+	  && $(MAKE) $(AM_MAKEFLAGS) install \
+	  && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+	  && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+	  && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+	        distuninstallcheck \
+	  && chmod -R a-w "$$dc_install_base" \
+	  && ({ \
+	       (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+	            distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+	      } || { rm -rf "$$dc_destdir"; exit 1; }) \
+	  && rm -rf "$$dc_destdir" \
+	  && $(MAKE) $(AM_MAKEFLAGS) dist \
+	  && rm -rf $(DIST_ARCHIVES) \
+	  && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
+	  && cd "$$am__cwd" \
+	  || exit 1
+	$(am__post_remove_distdir)
+	@(echo "$(distdir) archives ready for distribution: "; \
+	  list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+	  sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
+distuninstallcheck:
+	@test -n '$(distuninstallcheck_dir)' || { \
+	  echo 'ERROR: trying to run $@ with an empty' \
+	       '$$(distuninstallcheck_dir)' >&2; \
+	  exit 1; \
+	}; \
+	$(am__cd) '$(distuninstallcheck_dir)' || { \
+	  echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \
+	  exit 1; \
+	}; \
+	test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \
+	   || { echo "ERROR: files left after uninstall:" ; \
+	        if test -n "$(DESTDIR)"; then \
+	          echo "  (check DESTDIR support)"; \
+	        fi ; \
+	        $(distuninstallcheck_listfiles) ; \
+	        exit 1; } >&2
+distcleancheck: distclean
+	@if test '$(srcdir)' = . ; then \
+	  echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+	  exit 1 ; \
+	fi
+	@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+	  || { echo "ERROR: files left in build directory after distclean:" ; \
+	       $(distcleancheck_listfiles) ; \
+	       exit 1; } >&2
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES) config.h
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-hdr distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+	-rm -rf $(top_srcdir)/autom4te.cache
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: all install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--refresh check check-am clean \
+	clean-cscope clean-generic clean-noinstLIBRARIES cscope \
+	cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \
+	dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \
+	distcheck distclean distclean-compile distclean-generic \
+	distclean-hdr distclean-tags distcleancheck distdir \
+	distuninstallcheck dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am install-man \
+	install-pdf install-pdf-am install-ps install-ps-am \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \
+	tags tags-am uninstall uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/libctf/aclocal.m4 b/libctf/aclocal.m4
new file mode 100644
index 0000000000..d792e62dfb
--- /dev/null
+++ b/libctf/aclocal.m4
@@ -0,0 +1,1233 @@
+# generated automatically by aclocal 1.15.1 -*- Autoconf -*-
+
+# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
+[m4_warning([this file was generated for autoconf 2.69.
+You have another version of autoconf.  It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically 'autoreconf'.])])
+
+# Copyright (C) 2002-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.15'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version.  Point them to the right macro.
+m4_if([$1], [1.15.1], [],
+      [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too.  Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.15.1])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+
+# Copyright (C) 2011-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_AR([ACT-IF-FAIL])
+# -------------------------
+# Try to determine the archiver interface, and trigger the ar-lib wrapper
+# if it is needed.  If the detection of archiver interface fails, run
+# ACT-IF-FAIL (default is to abort configure with a proper error message).
+AC_DEFUN([AM_PROG_AR],
+[AC_BEFORE([$0], [LT_INIT])dnl
+AC_BEFORE([$0], [AC_PROG_LIBTOOL])dnl
+AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([ar-lib])dnl
+AC_CHECK_TOOLS([AR], [ar lib "link -lib"], [false])
+: ${AR=ar}
+
+AC_CACHE_CHECK([the archiver ($AR) interface], [am_cv_ar_interface],
+  [AC_LANG_PUSH([C])
+   am_cv_ar_interface=ar
+   AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int some_variable = 0;]])],
+     [am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&AS_MESSAGE_LOG_FD'
+      AC_TRY_EVAL([am_ar_try])
+      if test "$ac_status" -eq 0; then
+        am_cv_ar_interface=ar
+      else
+        am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&AS_MESSAGE_LOG_FD'
+        AC_TRY_EVAL([am_ar_try])
+        if test "$ac_status" -eq 0; then
+          am_cv_ar_interface=lib
+        else
+          am_cv_ar_interface=unknown
+        fi
+      fi
+      rm -f conftest.lib libconftest.a
+     ])
+   AC_LANG_POP([C])])
+
+case $am_cv_ar_interface in
+ar)
+  ;;
+lib)
+  # Microsoft lib, so override with the ar-lib wrapper script.
+  # FIXME: It is wrong to rewrite AR.
+  # But if we don't then we get into trouble of one sort or another.
+  # A longer-term fix would be to have automake use am__AR in this case,
+  # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something
+  # similar.
+  AR="$am_aux_dir/ar-lib $AR"
+  ;;
+unknown)
+  m4_default([$1],
+             [AC_MSG_ERROR([could not determine $AR interface])])
+  ;;
+esac
+AC_SUBST([AR])dnl
+])
+
+# AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
+
+# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to '$srcdir/foo'.  In other projects, it is set to
+# '$srcdir', '$srcdir/..', or '$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory.  The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run.  This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+#    fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+#    fails if $ac_aux_dir is absolute,
+#    fails when called from a subdirectory in a VPATH build with
+#          a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir.  In an in-source build this is usually
+# harmless because $srcdir is '.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir.  That would be:
+#   am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+#   MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH.  The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
+# Expand $ac_aux_dir to an absolute path.
+am_aux_dir=`cd "$ac_aux_dir" && pwd`
+])
+
+# AM_CONDITIONAL                                            -*- Autoconf -*-
+
+# Copyright (C) 1997-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ([2.52])dnl
+ m4_if([$1], [TRUE],  [AC_FATAL([$0: invalid condition: $1])],
+       [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+m4_define([_AM_COND_VALUE_$1], [$2])dnl
+if $2; then
+  $1_TRUE=
+  $1_FALSE='#'
+else
+  $1_TRUE='#'
+  $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+  AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+
+# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery.  Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+m4_if([$1], [CC],   [depcc="$CC"   am_compiler_list=],
+      [$1], [CXX],  [depcc="$CXX"  am_compiler_list=],
+      [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+      [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'],
+      [$1], [UPC],  [depcc="$UPC"  am_compiler_list=],
+      [$1], [GCJ],  [depcc="$GCJ"  am_compiler_list='gcc3 gcc'],
+                    [depcc="$$1"   am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+               [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named 'D' -- because '-MD' means "put the output
+  # in D".
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_$1_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+  fi
+  am__universal=false
+  m4_case([$1], [CC],
+    [case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac],
+    [CXX],
+    [case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac])
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+      # Solaris 10 /bin/sh.
+      echo '/* dummy */' > sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with '-c' and '-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle '-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs.
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # After this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested.
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+      # This compiler won't grok '-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_$1_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES.
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE([dependency-tracking], [dnl
+AS_HELP_STRING(
+  [--enable-dependency-tracking],
+  [do not reject slow dependency extractors])
+AS_HELP_STRING(
+  [--disable-dependency-tracking],
+  [speeds up one-time build])])
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+  am__nodep='_no'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+AC_SUBST([am__nodep])dnl
+_AM_SUBST_NOTMAKE([am__nodep])dnl
+])
+
+# Generate code to set up dependency tracking.              -*- Autoconf -*-
+
+# Copyright (C) 1999-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[{
+  # Older Autoconf quotes --file arguments for eval, but not when files
+  # are listed without --file.  Let's play safe and only enable the eval
+  # if we detect the quoting.
+  case $CONFIG_FILES in
+  *\'*) eval set x "$CONFIG_FILES" ;;
+  *)   set x $CONFIG_FILES ;;
+  esac
+  shift
+  for mf
+  do
+    # Strip MF so we end up with the name of the file.
+    mf=`echo "$mf" | sed -e 's/:.*$//'`
+    # Check whether this is an Automake generated Makefile or not.
+    # We used to match only the files named 'Makefile.in', but
+    # some people rename them; so instead we look at the file content.
+    # Grep'ing the first line is not enough: some people post-process
+    # each Makefile.in and add a new line on top of each file to say so.
+    # Grep'ing the whole file is not good either: AIX grep has a line
+    # limit of 2048, but all sed's we know have understand at least 4000.
+    if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+      dirpart=`AS_DIRNAME("$mf")`
+    else
+      continue
+    fi
+    # Extract the definition of DEPDIR, am__include, and am__quote
+    # from the Makefile without running 'make'.
+    DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+    test -z "$DEPDIR" && continue
+    am__include=`sed -n 's/^am__include = //p' < "$mf"`
+    test -z "$am__include" && continue
+    am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+    # Find all dependency output files, they are included files with
+    # $(DEPDIR) in their names.  We invoke sed twice because it is the
+    # simplest approach to changing $(DEPDIR) to its actual value in the
+    # expansion.
+    for file in `sed -n "
+      s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+	 sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
+      # Make sure the directory exists.
+      test -f "$dirpart/$file" && continue
+      fdir=`AS_DIRNAME(["$file"])`
+      AS_MKDIR_P([$dirpart/$fdir])
+      # echo "creating $dirpart/$file"
+      echo '# dummy' > "$dirpart/$file"
+    done
+  done
+}
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled.  FIXME.  This creates each '.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+     [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+     [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Do all the work for Automake.                             -*- Autoconf -*-
+
+# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This macro actually does too much.  Some checks are only needed if
+# your package does certain things.  But this isn't really a big deal.
+
+dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O.
+m4_define([AC_PROG_CC],
+m4_defn([AC_PROG_CC])
+[_AM_PROG_CC_C_O
+])
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out.  PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition.  After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.65])dnl
+dnl Autoconf wants to disallow AM_ names.  We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[AC_DIAGNOSE([obsolete],
+             [$0: two- and three-arguments forms are deprecated.])
+m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(
+  m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]),
+  [ok:ok],,
+  [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package])
+ AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}])
+AM_MISSING_PROG([AUTOCONF], [autoconf])
+AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}])
+AM_MISSING_PROG([AUTOHEADER], [autoheader])
+AM_MISSING_PROG([MAKEINFO], [makeinfo])
+AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+# For better backward compatibility.  To be removed once Automake 1.9.x
+# dies out for good.  For more background, see:
+# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
+# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
+AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
+# We need awk for the "check" target (and possibly the TAP driver).  The
+# system "awk" is bad on some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+	      [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+			     [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+		  [_AM_DEPENDENCIES([CC])],
+		  [m4_define([AC_PROG_CC],
+			     m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+		  [_AM_DEPENDENCIES([CXX])],
+		  [m4_define([AC_PROG_CXX],
+			     m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+		  [_AM_DEPENDENCIES([OBJC])],
+		  [m4_define([AC_PROG_OBJC],
+			     m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
+		  [_AM_DEPENDENCIES([OBJCXX])],
+		  [m4_define([AC_PROG_OBJCXX],
+			     m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
+])
+AC_REQUIRE([AM_SILENT_RULES])dnl
+dnl The testsuite driver may need to know about EXEEXT, so add the
+dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen.  This
+dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below.
+AC_CONFIG_COMMANDS_PRE(dnl
+[m4_provide_if([_AM_COMPILER_EXEEXT],
+  [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
+
+# POSIX will say in a future version that running "rm -f" with no argument
+# is OK; and we want to be able to make that assumption in our Makefile
+# recipes.  So use an aggressive probe to check that the usage we want is
+# actually supported "in the wild" to an acceptable degree.
+# See automake bug#10828.
+# To make any issue more visible, cause the running configure to be aborted
+# by default if the 'rm' program in use doesn't match our expectations; the
+# user can still override this though.
+if rm -f && rm -fr && rm -rf; then : OK; else
+  cat >&2 <<'END'
+Oops!
+
+Your 'rm' program seems unable to run without file operands specified
+on the command line, even when the '-f' option is present.  This is contrary
+to the behaviour of most rm programs out there, and not conforming with
+the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
+
+Please tell bug-automake@gnu.org about your system, including the value
+of your $PATH and any error possibly output before this message.  This
+can help us improve future automake versions.
+
+END
+  if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
+    echo 'Configuration will proceed anyway, since you have set the' >&2
+    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
+    echo >&2
+  else
+    cat >&2 <<'END'
+Aborting the configuration process, to ensure you take notice of the issue.
+
+You can download and install GNU coreutils to get an 'rm' implementation
+that behaves properly: <http://www.gnu.org/software/coreutils/>.
+
+If you want to complete the configuration process using your problematic
+'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
+to "yes", and re-run configure.
+
+END
+    AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
+  fi
+fi
+dnl The trailing newline in this macro's definition is deliberate, for
+dnl backward compatibility and to allow trailing 'dnl'-style comments
+dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841.
+])
+
+dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion.  Do not
+dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
+dnl mangled by Autoconf and run in a shell conditional statement.
+m4_define([_AC_COMPILER_EXEEXT],
+m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated.  The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+if test x"${install_sh+set}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+  *)
+    install_sh="\${SHELL} $am_aux_dir/install-sh"
+  esac
+fi
+AC_SUBST([install_sh])])
+
+# Add --enable-maintainer-mode option to configure.         -*- Autoconf -*-
+# From Jim Meyering
+
+# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MAINTAINER_MODE([DEFAULT-MODE])
+# ----------------------------------
+# Control maintainer-specific portions of Makefiles.
+# Default is to disable them, unless 'enable' is passed literally.
+# For symmetry, 'disable' may be passed as well.  Anyway, the user
+# can override the default with the --enable/--disable switch.
+AC_DEFUN([AM_MAINTAINER_MODE],
+[m4_case(m4_default([$1], [disable]),
+       [enable], [m4_define([am_maintainer_other], [disable])],
+       [disable], [m4_define([am_maintainer_other], [enable])],
+       [m4_define([am_maintainer_other], [enable])
+        m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])])
+AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
+  dnl maintainer-mode's default is 'disable' unless 'enable' is passed
+  AC_ARG_ENABLE([maintainer-mode],
+    [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode],
+      am_maintainer_other[ make rules and dependencies not useful
+      (and sometimes confusing) to the casual installer])],
+    [USE_MAINTAINER_MODE=$enableval],
+    [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes]))
+  AC_MSG_RESULT([$USE_MAINTAINER_MODE])
+  AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes])
+  MAINT=$MAINTAINER_MODE_TRUE
+  AC_SUBST([MAINT])dnl
+]
+)
+
+# Check to see how 'make' treats includes.	            -*- Autoconf -*-
+
+# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+	@echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from 'make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+  am__include=include
+  am__quote=
+  _am_result=GNU
+  ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   case `$am_make -s -f confmf 2> /dev/null` in #(
+   *the\ am__doit\ target*)
+     am__include=.include
+     am__quote="\""
+     _am_result=BSD
+     ;;
+   esac
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
+
+# Copyright (C) 1997-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it is modern enough.
+# If it is, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+if test x"${MISSING+set}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+  *)
+    MISSING="\${SHELL} $am_aux_dir/missing" ;;
+  esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --is-lightweight"; then
+  am_missing_run="$MISSING "
+else
+  am_missing_run=
+  AC_MSG_WARN(['missing' script is too old or missing])
+fi
+])
+
+# Helper functions for option handling.                     -*- Autoconf -*-
+
+# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# --------------------
+# Set option NAME.  Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), [1])])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Copyright (C) 1999-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_PROG_CC_C_O
+# ---------------
+# Like AC_PROG_CC_C_O, but changed for automake.  We rewrite AC_PROG_CC
+# to automatically call this.
+AC_DEFUN([_AM_PROG_CC_C_O],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([compile])dnl
+AC_LANG_PUSH([C])dnl
+AC_CACHE_CHECK(
+  [whether $CC understands -c and -o together],
+  [am_cv_prog_cc_c_o],
+  [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])])
+  # Make sure it works both with $CC and with simple cc.
+  # Following AC_PROG_CC_C_O, we do the test twice because some
+  # compilers refuse to overwrite an existing .o file with -o,
+  # though they will create one.
+  am_cv_prog_cc_c_o=yes
+  for am_i in 1 2; do
+    if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \
+         && test -f conftest2.$ac_objext; then
+      : OK
+    else
+      am_cv_prog_cc_c_o=no
+      break
+    fi
+  done
+  rm -f core conftest*
+  unset am_i])
+if test "$am_cv_prog_cc_c_o" != yes; then
+   # Losing compiler, so override with the script.
+   # FIXME: It is wrong to rewrite CC.
+   # But if we don't then we get into trouble of one sort or another.
+   # A longer-term fix would be to have automake use am__CC in this case,
+   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+   CC="$am_aux_dir/compile $CC"
+fi
+AC_LANG_POP([C])])
+
+# For backward compatibility.
+AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
+
+# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_RUN_LOG(COMMAND)
+# -------------------
+# Run COMMAND, save the exit status in ac_status, and log it.
+# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
+AC_DEFUN([AM_RUN_LOG],
+[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
+   ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   (exit $ac_status); }])
+
+# Check to make sure that the build environment is sane.    -*- Autoconf -*-
+
+# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name.  Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+  *[[\\\"\#\$\&\'\`$am_lf]]*)
+    AC_MSG_ERROR([unsafe absolute working directory name]);;
+esac
+case $srcdir in
+  *[[\\\"\#\$\&\'\`$am_lf\ \	]]*)
+    AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);;
+esac
+
+# Do 'set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   am_has_slept=no
+   for am_try in 1 2; do
+     echo "timestamp, slept: $am_has_slept" > conftest.file
+     set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+     if test "$[*]" = "X"; then
+	# -L didn't work.
+	set X `ls -t "$srcdir/configure" conftest.file`
+     fi
+     if test "$[*]" != "X $srcdir/configure conftest.file" \
+	&& test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+	# If neither matched, then we have a broken ls.  This can happen
+	# if, for instance, CONFIG_SHELL is bash and it inherits a
+	# broken ls alias from the environment.  This has actually
+	# happened.  Such a system could not be considered "sane".
+	AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
+  alias in your environment])
+     fi
+     if test "$[2]" = conftest.file || test $am_try -eq 2; then
+       break
+     fi
+     # Just in case.
+     sleep 1
+     am_has_slept=yes
+   done
+   test "$[2]" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT([yes])
+# If we didn't sleep, we still need to ensure time stamps of config.status and
+# generated files are strictly newer.
+am_sleep_pid=
+if grep 'slept: no' conftest.file >/dev/null 2>&1; then
+  ( sleep 1 ) &
+  am_sleep_pid=$!
+fi
+AC_CONFIG_COMMANDS_PRE(
+  [AC_MSG_CHECKING([that generated files are newer than configure])
+   if test -n "$am_sleep_pid"; then
+     # Hide warnings about reused PIDs.
+     wait $am_sleep_pid 2>/dev/null
+   fi
+   AC_MSG_RESULT([done])])
+rm -f conftest.file
+])
+
+# Copyright (C) 2009-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_SILENT_RULES([DEFAULT])
+# --------------------------
+# Enable less verbose build rules; with the default set to DEFAULT
+# ("yes" being less verbose, "no" or empty being verbose).
+AC_DEFUN([AM_SILENT_RULES],
+[AC_ARG_ENABLE([silent-rules], [dnl
+AS_HELP_STRING(
+  [--enable-silent-rules],
+  [less verbose build output (undo: "make V=1")])
+AS_HELP_STRING(
+  [--disable-silent-rules],
+  [verbose build output (undo: "make V=0")])dnl
+])
+case $enable_silent_rules in @%:@ (((
+  yes) AM_DEFAULT_VERBOSITY=0;;
+   no) AM_DEFAULT_VERBOSITY=1;;
+    *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);;
+esac
+dnl
+dnl A few 'make' implementations (e.g., NonStop OS and NextStep)
+dnl do not support nested variable expansions.
+dnl See automake bug#9928 and bug#10237.
+am_make=${MAKE-make}
+AC_CACHE_CHECK([whether $am_make supports nested variables],
+   [am_cv_make_support_nested_variables],
+   [if AS_ECHO([['TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+	@$(TRUE)
+.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then
+  am_cv_make_support_nested_variables=yes
+else
+  am_cv_make_support_nested_variables=no
+fi])
+if test $am_cv_make_support_nested_variables = yes; then
+  dnl Using '$V' instead of '$(V)' breaks IRIX make.
+  AM_V='$(V)'
+  AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+  AM_V=$AM_DEFAULT_VERBOSITY
+  AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AC_SUBST([AM_V])dnl
+AM_SUBST_NOTMAKE([AM_V])dnl
+AC_SUBST([AM_DEFAULT_V])dnl
+AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl
+AC_SUBST([AM_DEFAULT_VERBOSITY])dnl
+AM_BACKSLASH='\'
+AC_SUBST([AM_BACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
+])
+
+# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor 'install' (even GNU) is that you can't
+# specify the program used to strip binaries.  This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in "make install-strip", and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using 'strip' when the user
+# run "make install-strip".  However 'strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the 'STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be 'maybe'.
+if test "$cross_compiling" != no; then
+  AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# AM_SUBST_NOTMAKE(VARIABLE)
+# --------------------------
+# Public sister of _AM_SUBST_NOTMAKE.
+AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
+
+# Check how to create a tarball.                            -*- Autoconf -*-
+
+# Copyright (C) 2004-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of 'v7', 'ustar', or 'pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+#     tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+#     $(am__untar) < result.tar
+#
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.  Yes, it's still used
+# in the wild :-(  We should find a proper way to deprecate it ...
+AC_SUBST([AMTAR], ['$${TAR-tar}'])
+
+# We'll loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+
+m4_if([$1], [v7],
+  [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
+
+  [m4_case([$1],
+    [ustar],
+     [# The POSIX 1988 'ustar' format is defined with fixed-size fields.
+      # There is notably a 21 bits limit for the UID and the GID.  In fact,
+      # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343
+      # and bug#13588).
+      am_max_uid=2097151 # 2^21 - 1
+      am_max_gid=$am_max_uid
+      # The $UID and $GID variables are not portable, so we need to resort
+      # to the POSIX-mandated id(1) utility.  Errors in the 'id' calls
+      # below are definitely unexpected, so allow the users to see them
+      # (that is, avoid stderr redirection).
+      am_uid=`id -u || echo unknown`
+      am_gid=`id -g || echo unknown`
+      AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format])
+      if test $am_uid -le $am_max_uid; then
+         AC_MSG_RESULT([yes])
+      else
+         AC_MSG_RESULT([no])
+         _am_tools=none
+      fi
+      AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format])
+      if test $am_gid -le $am_max_gid; then
+         AC_MSG_RESULT([yes])
+      else
+        AC_MSG_RESULT([no])
+        _am_tools=none
+      fi],
+
+  [pax],
+    [],
+
+  [m4_fatal([Unknown tar format])])
+
+  AC_MSG_CHECKING([how to create a $1 tar archive])
+
+  # Go ahead even if we have the value already cached.  We do so because we
+  # need to set the values for the 'am__tar' and 'am__untar' variables.
+  _am_tools=${am_cv_prog_tar_$1-$_am_tools}
+
+  for _am_tool in $_am_tools; do
+    case $_am_tool in
+    gnutar)
+      for _am_tar in tar gnutar gtar; do
+        AM_RUN_LOG([$_am_tar --version]) && break
+      done
+      am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+      am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+      am__untar="$_am_tar -xf -"
+      ;;
+    plaintar)
+      # Must skip GNU tar: if it does not support --format= it doesn't create
+      # ustar tarball either.
+      (tar --version) >/dev/null 2>&1 && continue
+      am__tar='tar chf - "$$tardir"'
+      am__tar_='tar chf - "$tardir"'
+      am__untar='tar xf -'
+      ;;
+    pax)
+      am__tar='pax -L -x $1 -w "$$tardir"'
+      am__tar_='pax -L -x $1 -w "$tardir"'
+      am__untar='pax -r'
+      ;;
+    cpio)
+      am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+      am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+      am__untar='cpio -i -H $1 -d'
+      ;;
+    none)
+      am__tar=false
+      am__tar_=false
+      am__untar=false
+      ;;
+    esac
+
+    # If the value was cached, stop now.  We just wanted to have am__tar
+    # and am__untar set.
+    test -n "${am_cv_prog_tar_$1}" && break
+
+    # tar/untar a dummy directory, and stop if the command works.
+    rm -rf conftest.dir
+    mkdir conftest.dir
+    echo GrepMe > conftest.dir/file
+    AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+    rm -rf conftest.dir
+    if test -s conftest.tar; then
+      AM_RUN_LOG([$am__untar <conftest.tar])
+      AM_RUN_LOG([cat conftest.dir/file])
+      grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+    fi
+  done
+  rm -rf conftest.dir
+
+  AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+  AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
+m4_include([../config/depstand.m4])
+m4_include([../config/lead-dot.m4])
+m4_include([../config/override.m4])
+m4_include([../config/warnings.m4])
diff --git a/libctf/config.h.in b/libctf/config.h.in
new file mode 100644
index 0000000000..8d87b3d08a
--- /dev/null
+++ b/libctf/config.h.in
@@ -0,0 +1,113 @@
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to 1 if you have the <byteswap.h> header file. */
+#undef HAVE_BYTESWAP_H
+
+/* Define to 1 if you have the `getpagesize' function. */
+#undef HAVE_GETPAGESIZE
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have a working `mmap' system call. */
+#undef HAVE_MMAP
+
+/* Define to 1 if you have the `pread' function. */
+#undef HAVE_PREAD
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Enable extensions on AIX 3, Interix.  */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# undef _GNU_SOURCE
+#endif
+/* Enable threading extensions on Solaris.  */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# undef _POSIX_PTHREAD_SEMANTICS
+#endif
+/* Enable extensions on HP NonStop.  */
+#ifndef _TANDEM_SOURCE
+# undef _TANDEM_SOURCE
+#endif
+/* Enable general extensions on Solaris.  */
+#ifndef __EXTENSIONS__
+# undef __EXTENSIONS__
+#endif
+
+
+/* Version number of package */
+#undef VERSION
+
+/* Enable large inode numbers on Mac OS X 10.5.  */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* Define to 1 if on MINIX. */
+#undef _MINIX
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+#undef _POSIX_1_SOURCE
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+#undef _POSIX_SOURCE
diff --git a/libctf/configure b/libctf/configure
new file mode 100755
index 0000000000..2213393673
--- /dev/null
+++ b/libctf/configure
@@ -0,0 +1,7462 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69 for libctf library 1.2.0-pre.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+  # into an infinite loop, continuously re-executing ourselves.
+  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+    _as_can_reexec=no; export _as_can_reexec;
+    # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+  fi
+  # We don't want this to propagate to other subprocesses.
+          { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+"
+  as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+  exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+  if (eval "$as_required") 2>/dev/null; then :
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  as_found=:
+  case $as_dir in #(
+	 /*)
+	   for as_base in sh bash ksh sh5; do
+	     # Try only shells that exist, to save several forks.
+	     as_shell=$as_dir/$as_base
+	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		    { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  CONFIG_SHELL=$as_shell as_have_required=yes
+		   if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  break 2
+fi
+fi
+	   done;;
+       esac
+  as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+	      { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+  CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+      if test "x$CONFIG_SHELL" != x; then :
+  export CONFIG_SHELL
+             # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+    if test x$as_have_required = xno; then :
+  $as_echo "$0: This script requires a shell more modern than all"
+  $as_echo "$0: the shells that I found on your system."
+  if test x${ZSH_VERSION+set} = xset ; then
+    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+  else
+    $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+  fi
+  exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+  # already done that, so ensure we don't try to do so again and fall
+  # in an infinite loop.  This has already happened in practice.
+  _as_can_reexec=no; export _as_can_reexec
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='libctf library'
+PACKAGE_TARNAME='libctf-library'
+PACKAGE_VERSION='1.2.0-pre'
+PACKAGE_STRING='libctf library 1.2.0-pre'
+PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
+
+ac_unique_file="ctf-impl.h"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_header_list=
+ac_subst_vars='am__EXEEXT_FALSE
+am__EXEEXT_TRUE
+LTLIBOBJS
+LIBOBJS
+ac_libctf_warn_cflags
+MAINT
+MAINTAINER_MODE_FALSE
+MAINTAINER_MODE_TRUE
+WERROR
+WARN_PEDANTIC
+c_warn
+warn
+ac_ct_AR
+AR
+RANLIB
+AM_BACKSLASH
+AM_DEFAULT_VERBOSITY
+AM_DEFAULT_V
+AM_V
+am__fastdepCC_FALSE
+am__fastdepCC_TRUE
+CCDEPMODE
+am__nodep
+AMDEPBACKSLASH
+AMDEP_FALSE
+AMDEP_TRUE
+am__quote
+am__include
+DEPDIR
+am__untar
+am__tar
+AMTAR
+am__leading_dot
+SET_MAKE
+AWK
+mkdir_p
+MKDIR_P
+INSTALL_STRIP_PROGRAM
+STRIP
+install_sh
+MAKEINFO
+AUTOHEADER
+AUTOMAKE
+AUTOCONF
+ACLOCAL
+VERSION
+PACKAGE
+CYGPATH_W
+am__isrc
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+EGREP
+GREP
+CPP
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_dependency_tracking
+enable_silent_rules
+enable_largefile
+enable_werror_always
+enable_maintainer_mode
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *=)   ac_optarg= ;;
+  *)    ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    case $ac_envvar in #(
+      '' | [0-9]* | *[!_$as_cr_alnum]* )
+      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+    esac
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
+		datadir sysconfdir sharedstatedir localstatedir includedir \
+		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+		libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_myself" : 'X\(//\)[^/]' \| \
+	 X"$as_myself" : 'X\(//\)$' \| \
+	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+	pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures libctf library 1.2.0-pre to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking ...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/libctf-library]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+Program names:
+  --program-prefix=PREFIX            prepend PREFIX to installed program names
+  --program-suffix=SUFFIX            append SUFFIX to installed program names
+  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of libctf library 1.2.0-pre:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-option-checking  ignore unrecognized --enable/--with options
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --enable-dependency-tracking
+                          do not reject slow dependency extractors
+  --disable-dependency-tracking
+                          speeds up one-time build
+  --enable-silent-rules   less verbose build output (undo: "make V=1")
+  --disable-silent-rules  verbose build output (undo: "make V=0")
+  --disable-largefile     omit support for large files
+  --enable-werror-always  enable -Werror despite compiler version
+  --enable-maintainer-mode
+                          enable make rules and dependencies not useful (and
+                          sometimes confusing) to the casual installer
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+libctf library configure 1.2.0-pre
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } > conftest.i && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+    ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if eval \${$3+:} false; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_header_compiler=yes
+else
+  ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  ac_header_preproc=yes
+else
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+  yes:no: )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+       $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=$ac_status
+fi
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 test -x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $2 (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by libctf library $as_me 1.2.0-pre, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    $as_echo "PATH: $as_dir"
+  done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+    2)
+      as_fn_append ac_configure_args1 " '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      as_fn_append ac_configure_args " '$ac_arg'"
+      ;;
+    esac
+  done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+	"s/'\''/'\''\\\\'\'''\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=\$$ac_var
+	case $ac_val in
+	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	esac
+	$as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  # We do not want a PATH search for config.site.
+  case $CONFIG_SITE in #((
+    -*)  ac_site_file1=./$CONFIG_SITE;;
+    */*) ac_site_file1=$CONFIG_SITE;;
+    *)   ac_site_file1=./$CONFIG_SITE;;
+  esac
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file" \
+      || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special files
+  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
+  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+as_fn_append ac_header_list " stdlib.h"
+as_fn_append ac_header_list " unistd.h"
+as_fn_append ac_header_list " sys/param.h"
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	# differences in whitespace do not lead to failure.
+	ac_old_val_w=`echo x $ac_old_val`
+	ac_new_val_w=`echo x $ac_new_val`
+	if test "$ac_old_val_w" != "$ac_new_val_w"; then
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	  ac_cache_corrupted=:
+	else
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+	  eval $ac_var=\$ac_old_val
+	fi
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+  if test -f "$ac_dir/install-sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f "$ac_dir/install.sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f "$ac_dir/shtool"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+# Expand $ac_aux_dir to an absolute path.
+am_aux_dir=`cd "$ac_aux_dir" && pwd`
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+	if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+	then :; else
+	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	fi
+	# We set ac_cv_exeext here because the later test for it is not
+	# safe: cross compilers may not add the suffix if given an `-o'
+	# argument, so we may need to know it at that point already.
+	# Even if this section looks crufty: it has the advantage of
+	# actually working.
+	break;;
+    * )
+	break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+if test -z "$ac_file"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+  { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+  if { ac_try='./conftest$ac_cv_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
+$as_echo_n "checking whether $CC understands -c and -o together... " >&6; }
+if ${am_cv_prog_cc_c_o+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+  # Make sure it works both with $CC and with simple cc.
+  # Following AC_PROG_CC_C_O, we do the test twice because some
+  # compilers refuse to overwrite an existing .o file with -o,
+  # though they will create one.
+  am_cv_prog_cc_c_o=yes
+  for am_i in 1 2; do
+    if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
+   ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); } \
+         && test -f conftest2.$ac_objext; then
+      : OK
+    else
+      am_cv_prog_cc_c_o=no
+      break
+    fi
+  done
+  rm -f core conftest*
+  unset am_i
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
+$as_echo "$am_cv_prog_cc_c_o" >&6; }
+if test "$am_cv_prog_cc_c_o" != yes; then
+   # Losing compiler, so override with the script.
+   # FIXME: It is wrong to rewrite CC.
+   # But if we don't then we get into trouble of one sort or another.
+   # A longer-term fix would be to have automake use am__CC in this case,
+   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+   CC="$am_aux_dir/compile $CC"
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if ${ac_cv_prog_CPP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in egrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_stdc=yes
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then :
+  :
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+		  inttypes.h stdint.h unistd.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+  ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default"
+if test "x$ac_cv_header_minix_config_h" = xyes; then :
+  MINIX=yes
+else
+  MINIX=
+fi
+
+
+  if test "$MINIX" = yes; then
+
+$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h
+
+
+$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h
+
+
+$as_echo "#define _MINIX 1" >>confdefs.h
+
+  fi
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5
+$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; }
+if ${ac_cv_safe_to_define___extensions__+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#         define __EXTENSIONS__ 1
+          $ac_includes_default
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_safe_to_define___extensions__=yes
+else
+  ac_cv_safe_to_define___extensions__=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5
+$as_echo "$ac_cv_safe_to_define___extensions__" >&6; }
+  test $ac_cv_safe_to_define___extensions__ = yes &&
+    $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h
+
+  $as_echo "#define _ALL_SOURCE 1" >>confdefs.h
+
+  $as_echo "#define _GNU_SOURCE 1" >>confdefs.h
+
+  $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h
+
+  $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h
+
+
+am__api_version='1.15'
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if ${ac_cv_path_install+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+  ./ | .// | /[cC]/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+	if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+	  if test $ac_prog = install &&
+	    grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # AIX install.  It has an incompatible calling convention.
+	    :
+	  elif test $ac_prog = install &&
+	    grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # program-specific install script used by HP pwplus--don't use.
+	    :
+	  else
+	    rm -rf conftest.one conftest.two conftest.dir
+	    echo one > conftest.one
+	    echo two > conftest.two
+	    mkdir conftest.dir
+	    if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+	      test -s conftest.one && test -s conftest.two &&
+	      test -s conftest.dir/conftest.one &&
+	      test -s conftest.dir/conftest.two
+	    then
+	      ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+	      break 3
+	    fi
+	  fi
+	fi
+      done
+    done
+    ;;
+esac
+
+  done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
+$as_echo_n "checking whether build environment is sane... " >&6; }
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name.  Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+  *[\\\"\#\$\&\'\`$am_lf]*)
+    as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;;
+esac
+case $srcdir in
+  *[\\\"\#\$\&\'\`$am_lf\ \	]*)
+    as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;;
+esac
+
+# Do 'set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   am_has_slept=no
+   for am_try in 1 2; do
+     echo "timestamp, slept: $am_has_slept" > conftest.file
+     set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+     if test "$*" = "X"; then
+	# -L didn't work.
+	set X `ls -t "$srcdir/configure" conftest.file`
+     fi
+     if test "$*" != "X $srcdir/configure conftest.file" \
+	&& test "$*" != "X conftest.file $srcdir/configure"; then
+
+	# If neither matched, then we have a broken ls.  This can happen
+	# if, for instance, CONFIG_SHELL is bash and it inherits a
+	# broken ls alias from the environment.  This has actually
+	# happened.  Such a system could not be considered "sane".
+	as_fn_error $? "ls -t appears to fail.  Make sure there is not a broken
+  alias in your environment" "$LINENO" 5
+     fi
+     if test "$2" = conftest.file || test $am_try -eq 2; then
+       break
+     fi
+     # Just in case.
+     sleep 1
+     am_has_slept=yes
+   done
+   test "$2" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   as_fn_error $? "newly created file is older than distributed files!
+Check your system clock" "$LINENO" 5
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+# If we didn't sleep, we still need to ensure time stamps of config.status and
+# generated files are strictly newer.
+am_sleep_pid=
+if grep 'slept: no' conftest.file >/dev/null 2>&1; then
+  ( sleep 1 ) &
+  am_sleep_pid=$!
+fi
+
+rm -f conftest.file
+
+test "$program_prefix" != NONE &&
+  program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.
+# By default was `s,x,x', remove it if useless.
+ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
+program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
+
+if test x"${MISSING+set}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+  *)
+    MISSING="\${SHELL} $am_aux_dir/missing" ;;
+  esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --is-lightweight"; then
+  am_missing_run="$MISSING "
+else
+  am_missing_run=
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5
+$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;}
+fi
+
+if test x"${install_sh+set}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+  *)
+    install_sh="\${SHELL} $am_aux_dir/install-sh"
+  esac
+fi
+
+# Installed binaries are usually stripped using 'strip' when the user
+# run "make install-strip".  However 'strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the 'STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5
+$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
+if test -z "$MKDIR_P"; then
+  if ${ac_cv_path_mkdir+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in mkdir gmkdir; do
+	 for ac_exec_ext in '' $ac_executable_extensions; do
+	   as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue
+	   case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+	     'mkdir (GNU coreutils) '* | \
+	     'mkdir (coreutils) '* | \
+	     'mkdir (fileutils) '4.1*)
+	       ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+	       break 3;;
+	   esac
+	 done
+       done
+  done
+IFS=$as_save_IFS
+
+fi
+
+  test -d ./--version && rmdir ./--version
+  if test "${ac_cv_path_mkdir+set}" = set; then
+    MKDIR_P="$ac_cv_path_mkdir -p"
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for MKDIR_P within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    MKDIR_P="$ac_install_sh -d"
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
+$as_echo "$MKDIR_P" >&6; }
+
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AWK+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_AWK="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$AWK" && break
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+	@echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+  *@@@%%%=?*=@@@%%%*)
+    eval ac_cv_prog_make_${ac_make}_set=yes;;
+  *)
+    eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+  SET_MAKE=
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+	@echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5
+$as_echo_n "checking for style of include used by $am_make... " >&6; }
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from 'make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+  am__include=include
+  am__quote=
+  _am_result=GNU
+  ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   case `$am_make -s -f confmf 2> /dev/null` in #(
+   *the\ am__doit\ target*)
+     am__include=.include
+     am__quote="\""
+     _am_result=BSD
+     ;;
+   esac
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5
+$as_echo "$_am_result" >&6; }
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then :
+  enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+  am__nodep='_no'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+  AMDEP_TRUE=
+  AMDEP_FALSE='#'
+else
+  AMDEP_TRUE='#'
+  AMDEP_FALSE=
+fi
+
+
+# Check whether --enable-silent-rules was given.
+if test "${enable_silent_rules+set}" = set; then :
+  enableval=$enable_silent_rules;
+fi
+
+case $enable_silent_rules in # (((
+  yes) AM_DEFAULT_VERBOSITY=0;;
+   no) AM_DEFAULT_VERBOSITY=1;;
+    *) AM_DEFAULT_VERBOSITY=1;;
+esac
+am_make=${MAKE-make}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
+$as_echo_n "checking whether $am_make supports nested variables... " >&6; }
+if ${am_cv_make_support_nested_variables+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if $as_echo 'TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+	@$(TRUE)
+.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
+  am_cv_make_support_nested_variables=yes
+else
+  am_cv_make_support_nested_variables=no
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
+$as_echo "$am_cv_make_support_nested_variables" >&6; }
+if test $am_cv_make_support_nested_variables = yes; then
+    AM_V='$(V)'
+  AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+  AM_V=$AM_DEFAULT_VERBOSITY
+  AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AM_BACKSLASH='\'
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  am__isrc=' -I$(srcdir)'
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE='libctf-library'
+ VERSION='1.2.0-pre'
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+# For better backward compatibility.  To be removed once Automake 1.9.x
+# dies out for good.  For more background, see:
+# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
+# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
+mkdir_p='$(MKDIR_P)'
+
+# We need awk for the "check" target (and possibly the TAP driver).  The
+# system "awk" is bad on some platforms.
+# Always define AMTAR for backward compatibility.  Yes, it's still used
+# in the wild :-(  We should find a proper way to deprecate it ...
+AMTAR='$${TAR-tar}'
+
+
+# We'll loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar  pax cpio none'
+
+am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
+
+
+
+
+
+depcc="$CC"   am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if ${am_cv_CC_dependencies_compiler_type+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named 'D' -- because '-MD' means "put the output
+  # in D".
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_CC_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  am__universal=false
+  case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+      # Solaris 10 /bin/sh.
+      echo '/* dummy */' > sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with '-c' and '-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle '-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs.
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # After this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested.
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+      # This compiler won't grok '-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_CC_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+  am__fastdepCC_TRUE=
+  am__fastdepCC_FALSE='#'
+else
+  am__fastdepCC_TRUE='#'
+  am__fastdepCC_FALSE=
+fi
+
+
+
+# POSIX will say in a future version that running "rm -f" with no argument
+# is OK; and we want to be able to make that assumption in our Makefile
+# recipes.  So use an aggressive probe to check that the usage we want is
+# actually supported "in the wild" to an acceptable degree.
+# See automake bug#10828.
+# To make any issue more visible, cause the running configure to be aborted
+# by default if the 'rm' program in use doesn't match our expectations; the
+# user can still override this though.
+if rm -f && rm -fr && rm -rf; then : OK; else
+  cat >&2 <<'END'
+Oops!
+
+Your 'rm' program seems unable to run without file operands specified
+on the command line, even when the '-f' option is present.  This is contrary
+to the behaviour of most rm programs out there, and not conforming with
+the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
+
+Please tell bug-automake@gnu.org about your system, including the value
+of your $PATH and any error possibly output before this message.  This
+can help us improve future automake versions.
+
+END
+  if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
+    echo 'Configuration will proceed anyway, since you have set the' >&2
+    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
+    echo >&2
+  else
+    cat >&2 <<'END'
+Aborting the configuration process, to ensure you take notice of the issue.
+
+You can download and install GNU coreutils to get an 'rm' implementation
+that behaves properly: <http://www.gnu.org/software/coreutils/>.
+
+If you want to complete the configuration process using your problematic
+'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
+to "yes", and re-run configure.
+
+END
+    as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5
+  fi
+fi
+
+
+# Checks for programs.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+	@echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+  *@@@%%%=?*=@@@%%%*)
+    eval ac_cv_prog_make_${ac_make}_set=yes;;
+  *)
+    eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+  SET_MAKE=
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
+$as_echo_n "checking whether $CC understands -c and -o together... " >&6; }
+if ${am_cv_prog_cc_c_o+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+  # Make sure it works both with $CC and with simple cc.
+  # Following AC_PROG_CC_C_O, we do the test twice because some
+  # compilers refuse to overwrite an existing .o file with -o,
+  # though they will create one.
+  am_cv_prog_cc_c_o=yes
+  for am_i in 1 2; do
+    if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
+   ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); } \
+         && test -f conftest2.$ac_objext; then
+      : OK
+    else
+      am_cv_prog_cc_c_o=no
+      break
+    fi
+  done
+  rm -f core conftest*
+  unset am_i
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
+$as_echo "$am_cv_prog_cc_c_o" >&6; }
+if test "$am_cv_prog_cc_c_o" != yes; then
+   # Losing compiler, so override with the script.
+   # FIXME: It is wrong to rewrite CC.
+   # But if we don't then we get into trouble of one sort or another.
+   # A longer-term fix would be to have automake use am__CC in this case,
+   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+   CC="$am_aux_dir/compile $CC"
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_RANLIB+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+if test -n "$ac_tool_prefix"; then
+  for ac_prog in ar lib "link -lib"
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AR"; then
+  ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_AR="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$AR" && break
+  done
+fi
+if test -z "$AR"; then
+  ac_ct_AR=$AR
+  for ac_prog in ar lib "link -lib"
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_AR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_AR"; then
+  ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_AR="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_AR" && break
+done
+
+  if test "x$ac_ct_AR" = x; then
+    AR="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    AR=$ac_ct_AR
+  fi
+fi
+
+: ${AR=ar}
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the archiver ($AR) interface" >&5
+$as_echo_n "checking the archiver ($AR) interface... " >&6; }
+if ${am_cv_ar_interface+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+   am_cv_ar_interface=ar
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int some_variable = 0;
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&5'
+      { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5
+  (eval $am_ar_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+      if test "$ac_status" -eq 0; then
+        am_cv_ar_interface=ar
+      else
+        am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&5'
+        { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5
+  (eval $am_ar_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+        if test "$ac_status" -eq 0; then
+          am_cv_ar_interface=lib
+        else
+          am_cv_ar_interface=unknown
+        fi
+      fi
+      rm -f conftest.lib libconftest.a
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_ar_interface" >&5
+$as_echo "$am_cv_ar_interface" >&6; }
+
+case $am_cv_ar_interface in
+ar)
+  ;;
+lib)
+  # Microsoft lib, so override with the ar-lib wrapper script.
+  # FIXME: It is wrong to rewrite AR.
+  # But if we don't then we get into trouble of one sort or another.
+  # A longer-term fix would be to have automake use am__AR in this case,
+  # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something
+  # similar.
+  AR="$am_aux_dir/ar-lib $AR"
+  ;;
+unknown)
+  as_fn_error $? "could not determine $AR interface" "$LINENO" 5
+  ;;
+esac
+
+
+# Check whether --enable-largefile was given.
+if test "${enable_largefile+set}" = set; then :
+  enableval=$enable_largefile;
+fi
+
+if test "$enable_largefile" != no; then
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5
+$as_echo_n "checking for special C compiler options needed for large files... " >&6; }
+if ${ac_cv_sys_largefile_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_sys_largefile_CC=no
+     if test "$GCC" != yes; then
+       ac_save_CC=$CC
+       while :; do
+	 # IRIX 6.2 and later do not support large files by default,
+	 # so use the C compiler's -n32 option if that helps.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+	 if ac_fn_c_try_compile "$LINENO"; then :
+  break
+fi
+rm -f core conftest.err conftest.$ac_objext
+	 CC="$CC -n32"
+	 if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_largefile_CC=' -n32'; break
+fi
+rm -f core conftest.err conftest.$ac_objext
+	 break
+       done
+       CC=$ac_save_CC
+       rm -f conftest.$ac_ext
+    fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5
+$as_echo "$ac_cv_sys_largefile_CC" >&6; }
+  if test "$ac_cv_sys_largefile_CC" != no; then
+    CC=$CC$ac_cv_sys_largefile_CC
+  fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; }
+if ${ac_cv_sys_file_offset_bits+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  while :; do
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_file_offset_bits=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#define _FILE_OFFSET_BITS 64
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_file_offset_bits=64; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  ac_cv_sys_file_offset_bits=unknown
+  break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5
+$as_echo "$ac_cv_sys_file_offset_bits" >&6; }
+case $ac_cv_sys_file_offset_bits in #(
+  no | unknown) ;;
+  *)
+cat >>confdefs.h <<_ACEOF
+#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
+_ACEOF
+;;
+esac
+rm -rf conftest*
+  if test $ac_cv_sys_file_offset_bits = unknown; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5
+$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; }
+if ${ac_cv_sys_large_files+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  while :; do
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_large_files=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#define _LARGE_FILES 1
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_large_files=1; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  ac_cv_sys_large_files=unknown
+  break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5
+$as_echo "$ac_cv_sys_large_files" >&6; }
+case $ac_cv_sys_large_files in #(
+  no | unknown) ;;
+  *)
+cat >>confdefs.h <<_ACEOF
+#define _LARGE_FILES $ac_cv_sys_large_files
+_ACEOF
+;;
+esac
+rm -rf conftest*
+  fi
+
+
+fi
+
+
+MISSING=`cd $ac_aux_dir && ${PWDCMD-pwd}`/missing
+for ac_prog in aclocal
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ACLOCAL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ACLOCAL"; then
+  ac_cv_prog_ACLOCAL="$ACLOCAL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ACLOCAL="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ACLOCAL=$ac_cv_prog_ACLOCAL
+if test -n "$ACLOCAL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ACLOCAL" >&5
+$as_echo "$ACLOCAL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ACLOCAL" && break
+done
+test -n "$ACLOCAL" || ACLOCAL="$MISSING aclocal"
+
+for ac_prog in autoconf
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AUTOCONF+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AUTOCONF"; then
+  ac_cv_prog_AUTOCONF="$AUTOCONF" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_AUTOCONF="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AUTOCONF=$ac_cv_prog_AUTOCONF
+if test -n "$AUTOCONF"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AUTOCONF" >&5
+$as_echo "$AUTOCONF" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$AUTOCONF" && break
+done
+test -n "$AUTOCONF" || AUTOCONF="$MISSING autoconf"
+
+for ac_prog in autoheader
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AUTOHEADER+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AUTOHEADER"; then
+  ac_cv_prog_AUTOHEADER="$AUTOHEADER" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_AUTOHEADER="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AUTOHEADER=$ac_cv_prog_AUTOHEADER
+if test -n "$AUTOHEADER"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AUTOHEADER" >&5
+$as_echo "$AUTOHEADER" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$AUTOHEADER" && break
+done
+test -n "$AUTOHEADER" || AUTOHEADER="$MISSING autoheader"
+
+
+# Figure out what compiler warnings we can enable.
+# See config/warnings.m4 for details.
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+warn=
+save_CFLAGS="$CFLAGS"
+for real_option in -W -Wall -Wno-narrowing -Wwrite-strings \
+			  -Wmissing-format-attribute; do
+  # Do the check with the no- prefix removed since gcc silently
+  # accepts any -Wno-* option on purpose
+  case $real_option in
+    -Wno-*) option=-W`expr x$real_option : 'x-Wno-\(.*\)'` ;;
+    *) option=$real_option ;;
+  esac
+  as_acx_Woption=`$as_echo "acx_cv_prog_cc_warning_$option" | $as_tr_sh`
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports $option" >&5
+$as_echo_n "checking whether $CC supports $option... " >&6; }
+if eval \${$as_acx_Woption+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  CFLAGS="$option"
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$as_acx_Woption=yes"
+else
+  eval "$as_acx_Woption=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+eval ac_res=\$$as_acx_Woption
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  if test `eval 'as_val=${'$as_acx_Woption'};$as_echo "$as_val"'` = yes; then :
+  warn="$warn${warn:+ }$real_option"
+fi
+  done
+CFLAGS="$save_CFLAGS"
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+c_warn=
+save_CFLAGS="$CFLAGS"
+for real_option in -Wstrict-prototypes -Wmissing-prototypes \
+			  -Wold-style-definition; do
+  # Do the check with the no- prefix removed since gcc silently
+  # accepts any -Wno-* option on purpose
+  case $real_option in
+    -Wno-*) option=-W`expr x$real_option : 'x-Wno-\(.*\)'` ;;
+    *) option=$real_option ;;
+  esac
+  as_acx_Woption=`$as_echo "acx_cv_prog_cc_warning_$option" | $as_tr_sh`
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports $option" >&5
+$as_echo_n "checking whether $CC supports $option... " >&6; }
+if eval \${$as_acx_Woption+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  CFLAGS="$option"
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$as_acx_Woption=yes"
+else
+  eval "$as_acx_Woption=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+eval ac_res=\$$as_acx_Woption
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  if test `eval 'as_val=${'$as_acx_Woption'};$as_echo "$as_val"'` = yes; then :
+  c_warn="$c_warn${c_warn:+ }$real_option"
+fi
+  done
+CFLAGS="$save_CFLAGS"
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+WARN_PEDANTIC=
+# Do the check with the no- prefix removed from the warning options
+# since gcc silently accepts any -Wno-* option on purpose
+if test "$GCC" = yes; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -pedantic -Wlong-long" >&5
+$as_echo_n "checking whether $CC supports -pedantic -Wlong-long... " >&6; }
+if ${acx_cv_prog_cc_pedantic__Wlong_long+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  save_CFLAGS="$CFLAGS"
+CFLAGS="-pedantic -Wlong-long"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  acx_cv_prog_cc_pedantic__Wlong_long=yes
+else
+  acx_cv_prog_cc_pedantic__Wlong_long=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+CFLAGS="$save_CFLAGS"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_cv_prog_cc_pedantic__Wlong_long" >&5
+$as_echo "$acx_cv_prog_cc_pedantic__Wlong_long" >&6; }
+if test $acx_cv_prog_cc_pedantic__Wlong_long = yes; then :
+  WARN_PEDANTIC="$WARN_PEDANTIC${WARN_PEDANTIC:+ }-pedantic -Wno-long-long"
+fi
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+# Only enable with --enable-werror-always until existing warnings are
+# corrected.
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+WERROR=
+# Check whether --enable-werror-always was given.
+if test "${enable_werror_always+set}" = set; then :
+  enableval=$enable_werror_always;
+else
+  enable_werror_always=no
+fi
+
+if test $enable_werror_always = yes; then :
+  WERROR="$WERROR${WERROR:+ }-Werror"
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
+$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
+    # Check whether --enable-maintainer-mode was given.
+if test "${enable_maintainer_mode+set}" = set; then :
+  enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval
+else
+  USE_MAINTAINER_MODE=no
+fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5
+$as_echo "$USE_MAINTAINER_MODE" >&6; }
+   if test $USE_MAINTAINER_MODE = yes; then
+  MAINTAINER_MODE_TRUE=
+  MAINTAINER_MODE_FALSE='#'
+else
+  MAINTAINER_MODE_TRUE='#'
+  MAINTAINER_MODE_FALSE=
+fi
+
+  MAINT=$MAINTAINER_MODE_TRUE
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_libctf_warn_cflags=
+save_CFLAGS="$CFLAGS"
+for real_option in -Wall; do
+  # Do the check with the no- prefix removed since gcc silently
+  # accepts any -Wno-* option on purpose
+  case $real_option in
+    -Wno-*) option=-W`expr x$real_option : 'x-Wno-\(.*\)'` ;;
+    *) option=$real_option ;;
+  esac
+  as_acx_Woption=`$as_echo "acx_cv_prog_cc_warning_$option" | $as_tr_sh`
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports $option" >&5
+$as_echo_n "checking whether $CC supports $option... " >&6; }
+if eval \${$as_acx_Woption+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  CFLAGS="$option"
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$as_acx_Woption=yes"
+else
+  eval "$as_acx_Woption=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+eval ac_res=\$$as_acx_Woption
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  if test `eval 'as_val=${'$as_acx_Woption'};$as_echo "$as_val"'` = yes; then :
+  ac_libctf_warn_cflags="$ac_libctf_warn_cflags${ac_libctf_warn_cflags:+ }$real_option"
+fi
+  done
+CFLAGS="$save_CFLAGS"
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+  for ac_header in $ac_header_list
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+
+
+
+
+for ac_func in getpagesize
+do :
+  ac_fn_c_check_func "$LINENO" "getpagesize" "ac_cv_func_getpagesize"
+if test "x$ac_cv_func_getpagesize" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GETPAGESIZE 1
+_ACEOF
+
+fi
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working mmap" >&5
+$as_echo_n "checking for working mmap... " >&6; }
+if ${ac_cv_func_mmap_fixed_mapped+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  ac_cv_func_mmap_fixed_mapped=no
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+/* malloc might have been renamed as rpl_malloc. */
+#undef malloc
+
+/* Thanks to Mike Haertel and Jim Avera for this test.
+   Here is a matrix of mmap possibilities:
+	mmap private not fixed
+	mmap private fixed at somewhere currently unmapped
+	mmap private fixed at somewhere already mapped
+	mmap shared not fixed
+	mmap shared fixed at somewhere currently unmapped
+	mmap shared fixed at somewhere already mapped
+   For private mappings, we should verify that changes cannot be read()
+   back from the file, nor mmap's back from the file at a different
+   address.  (There have been systems where private was not correctly
+   implemented like the infamous i386 svr4.0, and systems where the
+   VM page cache was not coherent with the file system buffer cache
+   like early versions of FreeBSD and possibly contemporary NetBSD.)
+   For shared mappings, we should conversely verify that changes get
+   propagated back to all the places they're supposed to be.
+
+   Grep wants private fixed already mapped.
+   The main things grep needs to know about mmap are:
+   * does it exist and is it safe to write into the mmap'd area
+   * how to use it (BSD variants)  */
+
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#if !defined STDC_HEADERS && !defined HAVE_STDLIB_H
+char *malloc ();
+#endif
+
+/* This mess was copied from the GNU getpagesize.h.  */
+#ifndef HAVE_GETPAGESIZE
+# ifdef _SC_PAGESIZE
+#  define getpagesize() sysconf(_SC_PAGESIZE)
+# else /* no _SC_PAGESIZE */
+#  ifdef HAVE_SYS_PARAM_H
+#   include <sys/param.h>
+#   ifdef EXEC_PAGESIZE
+#    define getpagesize() EXEC_PAGESIZE
+#   else /* no EXEC_PAGESIZE */
+#    ifdef NBPG
+#     define getpagesize() NBPG * CLSIZE
+#     ifndef CLSIZE
+#      define CLSIZE 1
+#     endif /* no CLSIZE */
+#    else /* no NBPG */
+#     ifdef NBPC
+#      define getpagesize() NBPC
+#     else /* no NBPC */
+#      ifdef PAGESIZE
+#       define getpagesize() PAGESIZE
+#      endif /* PAGESIZE */
+#     endif /* no NBPC */
+#    endif /* no NBPG */
+#   endif /* no EXEC_PAGESIZE */
+#  else /* no HAVE_SYS_PARAM_H */
+#   define getpagesize() 8192	/* punt totally */
+#  endif /* no HAVE_SYS_PARAM_H */
+# endif /* no _SC_PAGESIZE */
+
+#endif /* no HAVE_GETPAGESIZE */
+
+int
+main ()
+{
+  char *data, *data2, *data3;
+  const char *cdata2;
+  int i, pagesize;
+  int fd, fd2;
+
+  pagesize = getpagesize ();
+
+  /* First, make a file with some known garbage in it. */
+  data = (char *) malloc (pagesize);
+  if (!data)
+    return 1;
+  for (i = 0; i < pagesize; ++i)
+    *(data + i) = rand ();
+  umask (0);
+  fd = creat ("conftest.mmap", 0600);
+  if (fd < 0)
+    return 2;
+  if (write (fd, data, pagesize) != pagesize)
+    return 3;
+  close (fd);
+
+  /* Next, check that the tail of a page is zero-filled.  File must have
+     non-zero length, otherwise we risk SIGBUS for entire page.  */
+  fd2 = open ("conftest.txt", O_RDWR | O_CREAT | O_TRUNC, 0600);
+  if (fd2 < 0)
+    return 4;
+  cdata2 = "";
+  if (write (fd2, cdata2, 1) != 1)
+    return 5;
+  data2 = (char *) mmap (0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd2, 0L);
+  if (data2 == MAP_FAILED)
+    return 6;
+  for (i = 0; i < pagesize; ++i)
+    if (*(data2 + i))
+      return 7;
+  close (fd2);
+  if (munmap (data2, pagesize))
+    return 8;
+
+  /* Next, try to mmap the file at a fixed address which already has
+     something else allocated at it.  If we can, also make sure that
+     we see the same garbage.  */
+  fd = open ("conftest.mmap", O_RDWR);
+  if (fd < 0)
+    return 9;
+  if (data2 != mmap (data2, pagesize, PROT_READ | PROT_WRITE,
+		     MAP_PRIVATE | MAP_FIXED, fd, 0L))
+    return 10;
+  for (i = 0; i < pagesize; ++i)
+    if (*(data + i) != *(data2 + i))
+      return 11;
+
+  /* Finally, make sure that changes to the mapped area do not
+     percolate back to the file as seen by read().  (This is a bug on
+     some variants of i386 svr4.0.)  */
+  for (i = 0; i < pagesize; ++i)
+    *(data2 + i) = *(data2 + i) + 1;
+  data3 = (char *) malloc (pagesize);
+  if (!data3)
+    return 12;
+  if (read (fd, data3, pagesize) != pagesize)
+    return 13;
+  for (i = 0; i < pagesize; ++i)
+    if (*(data + i) != *(data3 + i))
+      return 14;
+  close (fd);
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_func_mmap_fixed_mapped=yes
+else
+  ac_cv_func_mmap_fixed_mapped=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_mmap_fixed_mapped" >&5
+$as_echo "$ac_cv_func_mmap_fixed_mapped" >&6; }
+if test $ac_cv_func_mmap_fixed_mapped = yes; then
+
+$as_echo "#define HAVE_MMAP 1" >>confdefs.h
+
+fi
+rm -f conftest.mmap conftest.txt
+
+for ac_header in byteswap.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "byteswap.h" "ac_cv_header_byteswap_h" "$ac_includes_default"
+if test "x$ac_cv_header_byteswap_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_BYTESWAP_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_func in pread
+do :
+  ac_fn_c_check_func "$LINENO" "pread" "ac_cv_func_pread"
+if test "x$ac_cv_func_pread" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_PREAD 1
+_ACEOF
+
+fi
+done
+
+
+ac_config_files="$ac_config_files Makefile"
+
+ac_config_headers="$ac_config_headers config.h"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes: double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \.
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    if test "x$cache_file" != "x/dev/null"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+      if test ! -f "$cache_file" || test -h "$cache_file"; then
+	cat confcache >"$cache_file"
+      else
+        case $cache_file in #(
+        */* | ?:*)
+	  mv -f confcache "$cache_file"$$ &&
+	  mv -f "$cache_file"$$ "$cache_file" ;; #(
+        *)
+	  mv -f confcache "$cache_file" ;;
+	esac
+      fi
+    fi
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5
+$as_echo_n "checking that generated files are newer than configure... " >&6; }
+   if test -n "$am_sleep_pid"; then
+     # Hide warnings about reused PIDs.
+     wait $am_sleep_pid 2>/dev/null
+   fi
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5
+$as_echo "done" >&6; }
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+  as_fn_error $? "conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+  as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+ if test -n "$EXEEXT"; then
+  am__EXEEXT_TRUE=
+  am__EXEEXT_FALSE='#'
+else
+  am__EXEEXT_TRUE='#'
+  am__EXEEXT_FALSE=
+fi
+
+if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
+  as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by libctf library $as_me 1.2.0-pre, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+      --config     print configuration, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+      --header=FILE[:TEMPLATE]
+                   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+libctf library config.status 1.2.0-pre
+configured by $0, generated by GNU Autoconf 2.69,
+  with options \\"\$ac_cs_config\\"
+
+Copyright (C)  Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+AWK='$AWK'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=?*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  --*=)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --config | --confi | --conf | --con | --co | --c )
+    $as_echo "$ac_cs_config"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    '') as_fn_error $? "missing file argument" ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+
+  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp= ac_tmp=
+  trap 'exit_status=$?
+  : "${ac_tmp:=$tmp}"
+  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+  trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = "\a"
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=[	 ]*/{
+h
+s///
+s/^/:/
+s/[	 ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[	 ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[	 ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+  ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+  if test -z "$ac_tt"; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any.  Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[	 ]*#[	 ]*define[	 ][	 ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  for (key in D) D_is_set[key] = 1
+  FS = "\a"
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+  line = \$ 0
+  split(line, arg, " ")
+  if (arg[1] == "#") {
+    defundef = arg[2]
+    mac1 = arg[3]
+  } else {
+    defundef = substr(arg[1], 2)
+    mac1 = arg[2]
+  }
+  split(mac1, mac2, "(") #)
+  macro = mac2[1]
+  prefix = substr(line, 1, index(line, defundef) - 1)
+  if (D_is_set[macro]) {
+    # Preserve the white space surrounding the "#".
+    print prefix "define", macro P[macro] D[macro]
+    next
+  } else {
+    # Replace #undef with comments.  This is necessary, for example,
+    # in the case of _POSIX_SOURCE, which is predefined and required
+    # on some systems where configure will not decide to define it.
+    if (defundef == "undef") {
+      print "/*", prefix defundef, macro, "*/"
+      next
+    }
+  }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+  as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS    :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$ac_tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
+	 # because $ac_f cannot contain `:'.
+	 test -f "$ac_f" ||
+	   case $ac_f in
+	   [\\/$]*) false;;
+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+	   esac ||
+	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+	`' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$ac_tmp/stdin" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  as_dir="$ac_dir"; as_fn_mkdir_p
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+  ac_MKDIR_P=$MKDIR_P
+  case $MKDIR_P in
+  [\\/$]* | ?:[\\/]* ) ;;
+  */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+  s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
+      "$ac_tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&2;}
+
+  rm -f "$ac_tmp/stdin"
+  case $ac_file in
+  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+  if test x"$ac_file" != x-; then
+    {
+      $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+    } >"$ac_tmp/config.h" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f "$ac_file"
+      mv "$ac_tmp/config.h" "$ac_file" \
+	|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    fi
+  else
+    $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+      || as_fn_error $? "could not create -" "$LINENO" 5
+  fi
+# Compute "$ac_file"'s index in $config_headers.
+_am_arg="$ac_file"
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
+$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$_am_arg" : 'X\(//\)[^/]' \| \
+	 X"$_am_arg" : 'X\(//\)$' \| \
+	 X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$_am_arg" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+  :C)  { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+$as_echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+  esac
+
+
+  case $ac_file$ac_mode in
+    "depfiles":C) test x"$AMDEP_TRUE" != x"" || {
+  # Older Autoconf quotes --file arguments for eval, but not when files
+  # are listed without --file.  Let's play safe and only enable the eval
+  # if we detect the quoting.
+  case $CONFIG_FILES in
+  *\'*) eval set x "$CONFIG_FILES" ;;
+  *)   set x $CONFIG_FILES ;;
+  esac
+  shift
+  for mf
+  do
+    # Strip MF so we end up with the name of the file.
+    mf=`echo "$mf" | sed -e 's/:.*$//'`
+    # Check whether this is an Automake generated Makefile or not.
+    # We used to match only the files named 'Makefile.in', but
+    # some people rename them; so instead we look at the file content.
+    # Grep'ing the first line is not enough: some people post-process
+    # each Makefile.in and add a new line on top of each file to say so.
+    # Grep'ing the whole file is not good either: AIX grep has a line
+    # limit of 2048, but all sed's we know have understand at least 4000.
+    if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+      dirpart=`$as_dirname -- "$mf" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$mf" : 'X\(//\)[^/]' \| \
+	 X"$mf" : 'X\(//\)$' \| \
+	 X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$mf" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+    else
+      continue
+    fi
+    # Extract the definition of DEPDIR, am__include, and am__quote
+    # from the Makefile without running 'make'.
+    DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+    test -z "$DEPDIR" && continue
+    am__include=`sed -n 's/^am__include = //p' < "$mf"`
+    test -z "$am__include" && continue
+    am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+    # Find all dependency output files, they are included files with
+    # $(DEPDIR) in their names.  We invoke sed twice because it is the
+    # simplest approach to changing $(DEPDIR) to its actual value in the
+    # expansion.
+    for file in `sed -n "
+      s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+	 sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
+      # Make sure the directory exists.
+      test -f "$dirpart/$file" && continue
+      fdir=`$as_dirname -- "$file" ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$file" : 'X\(//\)[^/]' \| \
+	 X"$file" : 'X\(//\)$' \| \
+	 X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      as_dir=$dirpart/$fdir; as_fn_mkdir_p
+      # echo "creating $dirpart/$file"
+      echo '# dummy' > "$dirpart/$file"
+    done
+  done
+}
+ ;;
+
+  esac
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/libctf/configure.ac b/libctf/configure.ac
new file mode 100644
index 0000000000..2d0cf86bb7
--- /dev/null
+++ b/libctf/configure.ac
@@ -0,0 +1,63 @@
+dnl                                            -*- Autoconf -*-
+dnl Process this file with autoconf to produce a configure script.
+dnl
+dnl   Copyright (C) 2019 Free Software Foundation, Inc.
+dnl
+dnl This file is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; see the file COPYING.  If not see
+dnl <http://www.gnu.org/licenses/>.
+dnl
+
+AC_PREREQ(2.64)
+AC_INIT([libctf library], 1.2.0-pre)
+AC_CONFIG_SRCDIR(ctf-impl.h)
+AC_CONFIG_MACRO_DIR(../config)
+AC_USE_SYSTEM_EXTENSIONS
+AM_INIT_AUTOMAKE
+
+# Checks for programs.
+AC_PROG_MAKE_SET
+AC_PROG_CC
+AC_PROG_RANLIB
+AM_PROG_AR
+
+AC_SYS_LARGEFILE
+
+MISSING=`cd $ac_aux_dir && ${PWDCMD-pwd}`/missing
+AC_CHECK_PROGS([ACLOCAL], [aclocal], [$MISSING aclocal])
+AC_CHECK_PROGS([AUTOCONF], [autoconf], [$MISSING autoconf])
+AC_CHECK_PROGS([AUTOHEADER], [autoheader], [$MISSING autoheader])
+
+# Figure out what compiler warnings we can enable.
+# See config/warnings.m4 for details.
+
+ACX_PROG_CC_WARNING_OPTS([-W -Wall -Wno-narrowing -Wwrite-strings \
+			  -Wmissing-format-attribute], [warn])
+ACX_PROG_CC_WARNING_OPTS([-Wstrict-prototypes -Wmissing-prototypes \
+			  -Wold-style-definition], [c_warn])
+ACX_PROG_CC_WARNING_ALMOST_PEDANTIC([-Wno-long-long])
+
+# Only enable with --enable-werror-always until existing warnings are
+# corrected.
+ACX_PROG_CC_WARNINGS_ARE_ERRORS([manual])
+
+AM_MAINTAINER_MODE
+ACX_PROG_CC_WARNING_OPTS([-Wall], [ac_libctf_warn_cflags])
+
+AC_FUNC_MMAP
+AC_CHECK_HEADERS(byteswap.h)
+AC_CHECK_FUNCS(pread)
+
+AC_CONFIG_FILES(Makefile)
+AC_CONFIG_HEADERS(config.h)
+AC_OUTPUT
-- 
2.21.0.237.gd0cfaa883d

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v2 11/19] libctf: core type lookup
  2019-05-17 22:10 [PATCH v2 00/19] libctf, and CTF support for objdump and readelf Nick Alcock
                   ` (17 preceding siblings ...)
  2019-05-17 22:12 ` [PATCH v2 16/19] libctf: labels Nick Alcock
@ 2019-05-17 22:12 ` Nick Alcock
  2019-05-20 19:27 ` [PATCH v2 00/19] libctf, and CTF support for objdump and readelf Joseph Myers
  2019-05-28  8:33 ` Nick Clifton
  20 siblings, 0 replies; 31+ messages in thread
From: Nick Alcock @ 2019-05-17 22:12 UTC (permalink / raw)
  To: binutils

Finally we get to the functions used to actually look up and enumerate
properties of types in a container (names, sizes, members, what type a
pointer or cv-qual references, determination of whether two types are
assignment-compatible, etc).

With a very few exceptions these do not work for types newly added via
ctf_add_*(): they only work on types in read-only containers, or types
added before the most recent call to ctf_update().

This also adds support for lookup of "variables" (string -> type ID
mappings) and for generation of C type names corresponding to a type ID.

Changes from v1:
 - Correct erroneous license (GPLv2+ -> v3+) and reset copyright years.
 - Adjust for ctf_free() prototype change.
 - Enums and integers are assignment-compatible with each other.

libctf/
	* ctf-decl.c: New file.
	* ctf-types.c: Likewise.
	* ctf-impl.h: New declarations.

include/
	* ctf-api.h (ctf_visit_f): New definition.
	(ctf_member_f): Likewise.
	(ctf_enum_f): Likewise.
	(ctf_variable_f): Likewise.
	(ctf_type_f): Likewise.
	(ctf_type_isparent): Likewise.
	(ctf_type_ischild): Likewise.
	(ctf_type_resolve): Likewise.
	(ctf_type_aname): Likewise.
	(ctf_type_lname): Likewise.
	(ctf_type_name): Likewise.
	(ctf_type_sizee): Likewise.
	(ctf_type_align): Likewise.
	(ctf_type_kind): Likewise.
	(ctf_type_reference): Likewise.
	(ctf_type_pointer): Likewise.
	(ctf_type_encoding): Likewise.
	(ctf_type_visit): Likewise.
	(ctf_type_cmp): Likewise.
	(ctf_type_compat): Likewise.
	(ctf_member_info): Likewise.
	(ctf_array_info): Likewise.
	(ctf_enum_name): Likewise.
	(ctf_enum_value): Likewise.
	(ctf_member_iter): Likewise.
	(ctf_enum_iter): Likewise.
	(ctf_type_iter): Likewise.
	(ctf_variable_iter): Likewise.
---
 include/ctf-api.h  |   37 ++
 libctf/ctf-decl.c  |  195 +++++++++
 libctf/ctf-impl.h  |    8 +
 libctf/ctf-types.c | 1023 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 1263 insertions(+)
 create mode 100644 libctf/ctf-decl.c
 create mode 100644 libctf/ctf-types.c

diff --git a/include/ctf-api.h b/include/ctf-api.h
index 4c532f2867..4dffa42565 100644
--- a/include/ctf-api.h
+++ b/include/ctf-api.h
@@ -203,6 +203,16 @@ enum
 #define	CTF_ADD_NONROOT	0	/* Type only visible in nested scope.  */
 #define	CTF_ADD_ROOT	1	/* Type visible at top-level scope.  */
 
+/* These typedefs are used to define the signature for callback functions
+   that can be used with the iteration and visit functions below.  */
+
+typedef int ctf_visit_f (const char *name, ctf_id_t type, unsigned long offset,
+			 int depth, void *arg);
+typedef int ctf_member_f (const char *name, ctf_id_t membtype,
+			  unsigned long offset, void *arg);
+typedef int ctf_enum_f (const char *name, int val, void *arg);
+typedef int ctf_variable_f (const char *name, ctf_id_t type, void *arg);
+typedef int ctf_type_f (ctf_id_t type, void *arg);
 extern ctf_file_t *ctf_simple_open (const char *, size_t, const char *, size_t,
 				   size_t, const char *, size_t, int *);
 extern ctf_file_t *ctf_bfdopen (struct bfd *, int *);
@@ -217,6 +227,8 @@ extern ctf_sect_t ctf_getdatasect (const ctf_file_t *);
 extern ctf_file_t *ctf_parent_file (ctf_file_t *);
 extern const char *ctf_parent_name (ctf_file_t *);
 extern void ctf_parent_name_set (ctf_file_t *, const char *);
+extern int ctf_type_isparent (ctf_file_t *, ctf_id_t);
+extern int ctf_type_ischild (ctf_file_t *, ctf_id_t);
 
 extern int ctf_import (ctf_file_t *, ctf_file_t *);
 extern int ctf_setmodel (ctf_file_t *, int);
@@ -227,6 +239,31 @@ extern void *ctf_getspecific (ctf_file_t *);
 
 extern int ctf_errno (ctf_file_t *);
 extern const char *ctf_errmsg (int);
+extern ctf_id_t ctf_type_resolve (ctf_file_t *, ctf_id_t);
+extern char *ctf_type_aname (ctf_file_t *, ctf_id_t);
+extern ssize_t ctf_type_lname (ctf_file_t *, ctf_id_t, char *, size_t);
+extern char *ctf_type_name (ctf_file_t *, ctf_id_t, char *, size_t);
+extern ssize_t ctf_type_size (ctf_file_t *, ctf_id_t);
+extern ssize_t ctf_type_align (ctf_file_t *, ctf_id_t);
+extern int ctf_type_kind (ctf_file_t *, ctf_id_t);
+extern ctf_id_t ctf_type_reference (ctf_file_t *, ctf_id_t);
+extern ctf_id_t ctf_type_pointer (ctf_file_t *, ctf_id_t);
+extern int ctf_type_encoding (ctf_file_t *, ctf_id_t, ctf_encoding_t *);
+extern int ctf_type_visit (ctf_file_t *, ctf_id_t, ctf_visit_f *, void *);
+extern int ctf_type_cmp (ctf_file_t *, ctf_id_t, ctf_file_t *, ctf_id_t);
+extern int ctf_type_compat (ctf_file_t *, ctf_id_t, ctf_file_t *, ctf_id_t);
+
+extern int ctf_member_info (ctf_file_t *, ctf_id_t, const char *,
+			    ctf_membinfo_t *);
+extern int ctf_array_info (ctf_file_t *, ctf_id_t, ctf_arinfo_t *);
+
+extern const char *ctf_enum_name (ctf_file_t *, ctf_id_t, int);
+extern int ctf_enum_value (ctf_file_t *, ctf_id_t, const char *, int *);
+
+extern int ctf_member_iter (ctf_file_t *, ctf_id_t, ctf_member_f *, void *);
+extern int ctf_enum_iter (ctf_file_t *, ctf_id_t, ctf_enum_f *, void *);
+extern int ctf_type_iter (ctf_file_t *, ctf_type_f *, void *);
+extern int ctf_variable_iter (ctf_file_t *, ctf_variable_f *, void *);
 extern ctf_id_t ctf_add_array (ctf_file_t *, uint32_t,
 			       const ctf_arinfo_t *);
 extern ctf_id_t ctf_add_const (ctf_file_t *, uint32_t, ctf_id_t);
diff --git a/libctf/ctf-decl.c b/libctf/ctf-decl.c
new file mode 100644
index 0000000000..c85982e4a3
--- /dev/null
+++ b/libctf/ctf-decl.c
@@ -0,0 +1,195 @@
+/* C declarator syntax glue.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+
+   This file is part of libctf.
+
+   libctf is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+   See the GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+/* CTF Declaration Stack
+
+   In order to implement ctf_type_name(), we must convert a type graph back
+   into a C type declaration.  Unfortunately, a type graph represents a storage
+   class ordering of the type whereas a type declaration must obey the C rules
+   for operator precedence, and the two orderings are frequently in conflict.
+   For example, consider these CTF type graphs and their C declarations:
+
+   CTF_K_POINTER -> CTF_K_FUNCTION -> CTF_K_INTEGER  : int (*)()
+   CTF_K_POINTER -> CTF_K_ARRAY -> CTF_K_INTEGER     : int (*)[]
+
+   In each case, parentheses are used to raise operator * to higher lexical
+   precedence, so the string form of the C declaration cannot be constructed by
+   walking the type graph links and forming the string from left to right.
+
+   The functions in this file build a set of stacks from the type graph nodes
+   corresponding to the C operator precedence levels in the appropriate order.
+   The code in ctf_type_name() can then iterate over the levels and nodes in
+   lexical precedence order and construct the final C declaration string.  */
+
+#include <ctf-impl.h>
+#include <string.h>
+
+void
+ctf_decl_init (ctf_decl_t *cd)
+{
+  int i;
+
+  memset (cd, 0, sizeof (ctf_decl_t));
+
+  for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++)
+    cd->cd_order[i] = CTF_PREC_BASE - 1;
+
+  cd->cd_qualp = CTF_PREC_BASE;
+  cd->cd_ordp = CTF_PREC_BASE;
+}
+
+void
+ctf_decl_fini (ctf_decl_t *cd)
+{
+  ctf_decl_node_t *cdp, *ndp;
+  int i;
+
+  for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++)
+    {
+      for (cdp = ctf_list_next (&cd->cd_nodes[i]); cdp != NULL; cdp = ndp)
+	{
+	  ndp = ctf_list_next (cdp);
+	  ctf_free (cdp);
+	}
+    }
+}
+
+void
+ctf_decl_push (ctf_decl_t *cd, ctf_file_t *fp, ctf_id_t type)
+{
+  ctf_decl_node_t *cdp;
+  ctf_decl_prec_t prec;
+  uint32_t kind, n = 1;
+  int is_qual = 0;
+
+  const ctf_type_t *tp;
+  ctf_arinfo_t ar;
+
+  if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
+    {
+      cd->cd_err = fp->ctf_errno;
+      return;
+    }
+
+  switch (kind = LCTF_INFO_KIND (fp, tp->ctt_info))
+    {
+    case CTF_K_ARRAY:
+      (void) ctf_array_info (fp, type, &ar);
+      ctf_decl_push (cd, fp, ar.ctr_contents);
+      n = ar.ctr_nelems;
+      prec = CTF_PREC_ARRAY;
+      break;
+
+    case CTF_K_TYPEDEF:
+      if (ctf_strptr (fp, tp->ctt_name)[0] == '\0')
+	{
+	  ctf_decl_push (cd, fp, tp->ctt_type);
+	  return;
+	}
+      prec = CTF_PREC_BASE;
+      break;
+
+    case CTF_K_FUNCTION:
+      ctf_decl_push (cd, fp, tp->ctt_type);
+      prec = CTF_PREC_FUNCTION;
+      break;
+
+    case CTF_K_POINTER:
+      ctf_decl_push (cd, fp, tp->ctt_type);
+      prec = CTF_PREC_POINTER;
+      break;
+
+    case CTF_K_SLICE:
+      ctf_decl_push (cd, fp, ctf_type_reference (fp, type));
+      prec = CTF_PREC_BASE;
+      break;
+
+    case CTF_K_VOLATILE:
+    case CTF_K_CONST:
+    case CTF_K_RESTRICT:
+      ctf_decl_push (cd, fp, tp->ctt_type);
+      prec = cd->cd_qualp;
+      is_qual++;
+      break;
+
+    default:
+      prec = CTF_PREC_BASE;
+    }
+
+  if ((cdp = ctf_alloc (sizeof (ctf_decl_node_t))) == NULL)
+    {
+      cd->cd_err = EAGAIN;
+      return;
+    }
+
+  cdp->cd_type = type;
+  cdp->cd_kind = kind;
+  cdp->cd_n = n;
+
+  if (ctf_list_next (&cd->cd_nodes[prec]) == NULL)
+    cd->cd_order[prec] = cd->cd_ordp++;
+
+  /* Reset cd_qualp to the highest precedence level that we've seen so
+     far that can be qualified (CTF_PREC_BASE or CTF_PREC_POINTER).  */
+
+  if (prec > cd->cd_qualp && prec < CTF_PREC_ARRAY)
+    cd->cd_qualp = prec;
+
+  /* C array declarators are ordered inside out so prepend them.  Also by
+     convention qualifiers of base types precede the type specifier (e.g.
+     const int vs. int const) even though the two forms are equivalent.  */
+
+  if (kind == CTF_K_ARRAY || (is_qual && prec == CTF_PREC_BASE))
+    ctf_list_prepend (&cd->cd_nodes[prec], cdp);
+  else
+    ctf_list_append (&cd->cd_nodes[prec], cdp);
+}
+
+_libctf_printflike_ (2, 3)
+void ctf_decl_sprintf (ctf_decl_t *cd, const char *format, ...)
+{
+  va_list ap;
+  char *str;
+  int n;
+
+  if (cd->cd_enomem)
+    return;
+
+  va_start (ap, format);
+  n = vasprintf (&str, format, ap);
+  va_end (ap);
+
+  if (n > 0)
+      cd->cd_buf = ctf_str_append (cd->cd_buf, str);
+
+  /* Sticky error condition.  */
+  if (n < 0)
+    {
+      free (cd->cd_buf);
+      cd->cd_buf = NULL;
+      cd->cd_enomem = 1;
+    }
+
+  free (str);
+}
+
+char *ctf_decl_buf (ctf_decl_t *cd)
+{
+  return cd->cd_buf;
+}
diff --git a/libctf/ctf-impl.h b/libctf/ctf-impl.h
index 3944cfeaee..80ce2c1c5b 100644
--- a/libctf/ctf-impl.h
+++ b/libctf/ctf-impl.h
@@ -314,6 +314,14 @@ extern void ctf_dvd_insert (ctf_file_t *, ctf_dvdef_t *);
 extern void ctf_dvd_delete (ctf_file_t *, ctf_dvdef_t *);
 extern ctf_dvdef_t *ctf_dvd_lookup (const ctf_file_t *, const char *);
 
+extern void ctf_decl_init (ctf_decl_t *);
+extern void ctf_decl_fini (ctf_decl_t *);
+extern void ctf_decl_push (ctf_decl_t *, ctf_file_t *, ctf_id_t);
+
+_libctf_printflike_ (2, 3)
+extern void ctf_decl_sprintf (ctf_decl_t *, const char *, ...);
+extern char *ctf_decl_buf (ctf_decl_t *cd);
+
 extern const char *ctf_strraw (ctf_file_t *, uint32_t);
 extern const char *ctf_strptr (ctf_file_t *, uint32_t);
 
diff --git a/libctf/ctf-types.c b/libctf/ctf-types.c
new file mode 100644
index 0000000000..a7fe5d0b18
--- /dev/null
+++ b/libctf/ctf-types.c
@@ -0,0 +1,1023 @@
+/* Type handling functions.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+
+   This file is part of libctf.
+
+   libctf is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+   See the GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <ctf-impl.h>
+#include <string.h>
+
+/* Determine whether a type is a parent or a child.  */
+
+int
+ctf_type_isparent (ctf_file_t *fp, ctf_id_t id)
+{
+  return (LCTF_TYPE_ISPARENT (fp, id));
+}
+
+int
+ctf_type_ischild (ctf_file_t * fp, ctf_id_t id)
+{
+  return (LCTF_TYPE_ISCHILD (fp, id));
+}
+
+/* Iterate over the members of a STRUCT or UNION.  We pass the name, member
+   type, and offset of each member to the specified callback function.  */
+
+int
+ctf_member_iter (ctf_file_t *fp, ctf_id_t type, ctf_member_f *func, void *arg)
+{
+  ctf_file_t *ofp = fp;
+  const ctf_type_t *tp;
+  ssize_t size, increment;
+  uint32_t kind, n;
+  int rc;
+
+  if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  (void) ctf_get_ctt_size (fp, tp, &size, &increment);
+  kind = LCTF_INFO_KIND (fp, tp->ctt_info);
+
+  if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
+    return (ctf_set_errno (ofp, ECTF_NOTSOU));
+
+  if (size < CTF_LSTRUCT_THRESH)
+    {
+      const ctf_member_t *mp = (const ctf_member_t *) ((uintptr_t) tp +
+						       increment);
+
+      for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, mp++)
+	{
+	  const char *name = ctf_strptr (fp, mp->ctm_name);
+	  if ((rc = func (name, mp->ctm_type, mp->ctm_offset, arg)) != 0)
+	    return rc;
+	}
+
+    }
+  else
+    {
+      const ctf_lmember_t *lmp = (const ctf_lmember_t *) ((uintptr_t) tp +
+							  increment);
+
+      for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, lmp++)
+	{
+	  const char *name = ctf_strptr (fp, lmp->ctlm_name);
+	  if ((rc = func (name, lmp->ctlm_type,
+			  (unsigned long) CTF_LMEM_OFFSET (lmp), arg)) != 0)
+	    return rc;
+	}
+    }
+
+  return 0;
+}
+
+/* Iterate over the members of an ENUM.  We pass the string name and associated
+   integer value of each enum element to the specified callback function.  */
+
+int
+ctf_enum_iter (ctf_file_t *fp, ctf_id_t type, ctf_enum_f *func, void *arg)
+{
+  ctf_file_t *ofp = fp;
+  const ctf_type_t *tp;
+  const ctf_enum_t *ep;
+  ssize_t increment;
+  uint32_t n;
+  int rc;
+
+  if ((type = ctf_type_resolve_unsliced (fp, type)) == CTF_ERR)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  if (LCTF_INFO_KIND (fp, tp->ctt_info) != CTF_K_ENUM)
+    return (ctf_set_errno (ofp, ECTF_NOTENUM));
+
+  (void) ctf_get_ctt_size (fp, tp, NULL, &increment);
+
+  ep = (const ctf_enum_t *) ((uintptr_t) tp + increment);
+
+  for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, ep++)
+    {
+      const char *name = ctf_strptr (fp, ep->cte_name);
+      if ((rc = func (name, ep->cte_value, arg)) != 0)
+	return rc;
+    }
+
+  return 0;
+}
+
+/* Iterate over every root (user-visible) type in the given CTF container.
+   We pass the type ID of each type to the specified callback function.  */
+
+int
+ctf_type_iter (ctf_file_t *fp, ctf_type_f *func, void *arg)
+{
+  ctf_id_t id, max = fp->ctf_typemax;
+  int rc, child = (fp->ctf_flags & LCTF_CHILD);
+
+  for (id = 1; id <= max; id++)
+    {
+      const ctf_type_t *tp = LCTF_INDEX_TO_TYPEPTR (fp, id);
+      if (LCTF_INFO_ISROOT (fp, tp->ctt_info)
+	  && (rc = func (LCTF_INDEX_TO_TYPE (fp, id, child), arg)) != 0)
+	return rc;
+    }
+
+  return 0;
+}
+
+/* Iterate over every variable in the given CTF container, in arbitrary order.
+   We pass the name of each variable to the specified callback function.  */
+
+int
+ctf_variable_iter (ctf_file_t *fp, ctf_variable_f *func, void *arg)
+{
+  unsigned long i;
+  int rc;
+
+  if ((fp->ctf_flags & LCTF_CHILD) && (fp->ctf_parent == NULL))
+    return ECTF_NOPARENT;
+
+  for (i = 0; i < fp->ctf_nvars; i++)
+    if ((rc = func (ctf_strptr (fp, fp->ctf_vars[i].ctv_name),
+		    fp->ctf_vars[i].ctv_type, arg)) != 0)
+      return rc;
+
+  return 0;
+}
+
+/* Follow a given type through the graph for TYPEDEF, VOLATILE, CONST, and
+   RESTRICT nodes until we reach a "base" type node.  This is useful when
+   we want to follow a type ID to a node that has members or a size.  To guard
+   against infinite loops, we implement simplified cycle detection and check
+   each link against itself, the previous node, and the topmost node.
+
+   Does not drill down through slices to their contained type.  */
+
+ctf_id_t
+ctf_type_resolve (ctf_file_t *fp, ctf_id_t type)
+{
+  ctf_id_t prev = type, otype = type;
+  ctf_file_t *ofp = fp;
+  const ctf_type_t *tp;
+
+  while ((tp = ctf_lookup_by_id (&fp, type)) != NULL)
+    {
+      switch (LCTF_INFO_KIND (fp, tp->ctt_info))
+	{
+	case CTF_K_TYPEDEF:
+	case CTF_K_VOLATILE:
+	case CTF_K_CONST:
+	case CTF_K_RESTRICT:
+	  if (tp->ctt_type == type || tp->ctt_type == otype
+	      || tp->ctt_type == prev)
+	    {
+	      ctf_dprintf ("type %ld cycle detected\n", otype);
+	      return (ctf_set_errno (ofp, ECTF_CORRUPT));
+	    }
+	  prev = type;
+	  type = tp->ctt_type;
+	  break;
+	default:
+	  return type;
+	}
+    }
+
+  return CTF_ERR;		/* errno is set for us.  */
+}
+
+/* Like ctf_type_resolve(), but traverse down through slices to their contained
+   type.  */
+
+ctf_id_t
+ctf_type_resolve_unsliced (ctf_file_t *fp, ctf_id_t type)
+{
+  const ctf_type_t *tp;
+
+  if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
+    return -1;
+
+  if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  if ((LCTF_INFO_KIND (fp, tp->ctt_info)) == CTF_K_SLICE)
+    return ctf_type_reference (fp, type);
+  return type;
+}
+
+/* Lookup the given type ID and return its name as a new dynamcally-allocated
+   string.  */
+
+char *
+ctf_type_aname (ctf_file_t *fp, ctf_id_t type)
+{
+  ctf_decl_t cd;
+  ctf_decl_node_t *cdp;
+  ctf_decl_prec_t prec, lp, rp;
+  int ptr, arr;
+  uint32_t k;
+  char *buf;
+
+  if (fp == NULL && type == CTF_ERR)
+    return NULL;	/* Simplify caller code by permitting CTF_ERR.  */
+
+  ctf_decl_init (&cd);
+  ctf_decl_push (&cd, fp, type);
+
+  if (cd.cd_err != 0)
+    {
+      ctf_decl_fini (&cd);
+      ctf_set_errno (fp, cd.cd_err);
+      return NULL;
+    }
+
+  /* If the type graph's order conflicts with lexical precedence order
+     for pointers or arrays, then we need to surround the declarations at
+     the corresponding lexical precedence with parentheses.  This can
+     result in either a parenthesized pointer (*) as in int (*)() or
+     int (*)[], or in a parenthesized pointer and array as in int (*[])().  */
+
+  ptr = cd.cd_order[CTF_PREC_POINTER] > CTF_PREC_POINTER;
+  arr = cd.cd_order[CTF_PREC_ARRAY] > CTF_PREC_ARRAY;
+
+  rp = arr ? CTF_PREC_ARRAY : ptr ? CTF_PREC_POINTER : -1;
+  lp = ptr ? CTF_PREC_POINTER : arr ? CTF_PREC_ARRAY : -1;
+
+  k = CTF_K_POINTER;		/* Avoid leading whitespace (see below).  */
+
+  for (prec = CTF_PREC_BASE; prec < CTF_PREC_MAX; prec++)
+    {
+      for (cdp = ctf_list_next (&cd.cd_nodes[prec]);
+	   cdp != NULL; cdp = ctf_list_next (cdp))
+	{
+	  ctf_file_t *rfp = fp;
+	  const ctf_type_t *tp = ctf_lookup_by_id (&rfp, cdp->cd_type);
+	  const char *name = ctf_strptr (rfp, tp->ctt_name);
+
+	  if (k != CTF_K_POINTER && k != CTF_K_ARRAY)
+	    ctf_decl_sprintf (&cd, " ");
+
+	  if (lp == prec)
+	    {
+	      ctf_decl_sprintf (&cd, "(");
+	      lp = -1;
+	    }
+
+	  switch (cdp->cd_kind)
+	    {
+	    case CTF_K_INTEGER:
+	    case CTF_K_FLOAT:
+	    case CTF_K_TYPEDEF:
+	      ctf_decl_sprintf (&cd, "%s", name);
+	      break;
+	    case CTF_K_POINTER:
+	      ctf_decl_sprintf (&cd, "*");
+	      break;
+	    case CTF_K_ARRAY:
+	      ctf_decl_sprintf (&cd, "[%u]", cdp->cd_n);
+	      break;
+	    case CTF_K_FUNCTION:
+	      ctf_decl_sprintf (&cd, "()");
+	      break;
+	    case CTF_K_STRUCT:
+	    case CTF_K_FORWARD:
+	      ctf_decl_sprintf (&cd, "struct %s", name);
+	      break;
+	    case CTF_K_UNION:
+	      ctf_decl_sprintf (&cd, "union %s", name);
+	      break;
+	    case CTF_K_ENUM:
+	      ctf_decl_sprintf (&cd, "enum %s", name);
+	      break;
+	    case CTF_K_VOLATILE:
+	      ctf_decl_sprintf (&cd, "volatile");
+	      break;
+	    case CTF_K_CONST:
+	      ctf_decl_sprintf (&cd, "const");
+	      break;
+	    case CTF_K_RESTRICT:
+	      ctf_decl_sprintf (&cd, "restrict");
+	      break;
+	    case CTF_K_SLICE:
+	      /* No representation: just changes encoding of contained type,
+		 which is not in any case printed.  Skip it.  */
+	      break;
+	    }
+
+	  k = cdp->cd_kind;
+	}
+
+      if (rp == prec)
+	ctf_decl_sprintf (&cd, ")");
+    }
+
+  if (cd.cd_enomem)
+    (void) ctf_set_errno (fp, ENOMEM);
+
+  buf = ctf_decl_buf (&cd);
+
+  ctf_decl_fini (&cd);
+  return buf;
+}
+
+/* Lookup the given type ID and print a string name for it into buf.  Return
+   the actual number of bytes (not including \0) needed to format the name.  */
+
+ssize_t
+ctf_type_lname (ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
+{
+  char *str = ctf_type_aname (fp, type);
+  size_t slen = strlen (str);
+
+  if (str == NULL)
+    return CTF_ERR;             /* errno is set for us */
+
+  snprintf (buf, len, "%s", str);
+  free (str);
+
+  if (slen >= len)
+    (void) ctf_set_errno (fp, ECTF_NAMELEN);
+
+  return slen;
+}
+
+/* Lookup the given type ID and print a string name for it into buf.  If buf
+   is too small, return NULL: the ECTF_NAMELEN error is set on 'fp' for us.  */
+
+char *
+ctf_type_name (ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
+{
+  ssize_t rv = ctf_type_lname (fp, type, buf, len);
+  return (rv >= 0 && (size_t) rv < len ? buf : NULL);
+}
+
+/* Resolve the type down to a base type node, and then return the size
+   of the type storage in bytes.  */
+
+ssize_t
+ctf_type_size (ctf_file_t *fp, ctf_id_t type)
+{
+  const ctf_type_t *tp;
+  ssize_t size;
+  ctf_arinfo_t ar;
+
+  if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
+    return -1;			/* errno is set for us.  */
+
+  if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
+    return -1;			/* errno is set for us.  */
+
+  switch (LCTF_INFO_KIND (fp, tp->ctt_info))
+    {
+    case CTF_K_POINTER:
+      return fp->ctf_dmodel->ctd_pointer;
+
+    case CTF_K_FUNCTION:
+      return 0;		/* Function size is only known by symtab.  */
+
+    case CTF_K_ENUM:
+      return fp->ctf_dmodel->ctd_int;
+
+    case CTF_K_ARRAY:
+      /* ctf_add_array() does not directly encode the element size, but
+	 requires the user to multiply to determine the element size.
+
+	 If ctf_get_ctt_size() returns nonzero, then use the recorded
+	 size instead.  */
+
+      if ((size = ctf_get_ctt_size (fp, tp, NULL, NULL)) > 0)
+	return size;
+
+      if (ctf_array_info (fp, type, &ar) == CTF_ERR
+	  || (size = ctf_type_size (fp, ar.ctr_contents)) == CTF_ERR)
+	return -1;		/* errno is set for us.  */
+
+      return size * ar.ctr_nelems;
+
+    default: /* including slices of enums, etc */
+      return (ctf_get_ctt_size (fp, tp, NULL, NULL));
+    }
+}
+
+/* Resolve the type down to a base type node, and then return the alignment
+   needed for the type storage in bytes.
+
+   XXX may need arch-dependent attention.  */
+
+ssize_t
+ctf_type_align (ctf_file_t *fp, ctf_id_t type)
+{
+  const ctf_type_t *tp;
+  ctf_file_t *ofp = fp;
+  int kind;
+
+  if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
+    return -1;			/* errno is set for us.  */
+
+  if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
+    return -1;			/* errno is set for us.  */
+
+  kind = LCTF_INFO_KIND (fp, tp->ctt_info);
+  switch (kind)
+    {
+    case CTF_K_POINTER:
+    case CTF_K_FUNCTION:
+      return fp->ctf_dmodel->ctd_pointer;
+
+    case CTF_K_ARRAY:
+      {
+	ctf_arinfo_t r;
+	if (ctf_array_info (fp, type, &r) == CTF_ERR)
+	  return -1;		/* errno is set for us.  */
+	return (ctf_type_align (fp, r.ctr_contents));
+      }
+
+    case CTF_K_STRUCT:
+    case CTF_K_UNION:
+      {
+	size_t align = 0;
+	ctf_dtdef_t *dtd;
+
+	if ((dtd = ctf_dynamic_type (ofp, type)) == NULL)
+	  {
+	    uint32_t n = LCTF_INFO_VLEN (fp, tp->ctt_info);
+	    ssize_t size, increment;
+	    const void *vmp;
+
+	    (void) ctf_get_ctt_size (fp, tp, &size, &increment);
+	    vmp = (unsigned char *) tp + increment;
+
+	    if (kind == CTF_K_STRUCT)
+	      n = MIN (n, 1);	/* Only use first member for structs.  */
+
+	    if (size < CTF_LSTRUCT_THRESH)
+	      {
+		const ctf_member_t *mp = vmp;
+		for (; n != 0; n--, mp++)
+		  {
+		    ssize_t am = ctf_type_align (fp, mp->ctm_type);
+		    align = MAX (align, am);
+		  }
+	      }
+	    else
+	      {
+		const ctf_lmember_t *lmp = vmp;
+		for (; n != 0; n--, lmp++)
+		  {
+		    ssize_t am = ctf_type_align (fp, lmp->ctlm_type);
+		    align = MAX (align, am);
+		  }
+	      }
+	  }
+	else
+	  {
+	      ctf_dmdef_t *dmd;
+
+	      for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
+		   dmd != NULL; dmd = ctf_list_next (dmd))
+		{
+		  ssize_t am = ctf_type_align (fp, dmd->dmd_type);
+		  align = MAX (align, am);
+		  if (kind == CTF_K_STRUCT)
+		    break;
+		}
+	  }
+
+	return align;
+      }
+
+    case CTF_K_ENUM:
+      return fp->ctf_dmodel->ctd_int;
+
+    default:  /* including slices of enums, etc */
+      return (ctf_get_ctt_size (fp, tp, NULL, NULL));
+    }
+}
+
+/* Return the kind (CTF_K_* constant) for the specified type ID.  */
+
+int
+ctf_type_kind_unsliced (ctf_file_t *fp, ctf_id_t type)
+{
+  const ctf_type_t *tp;
+
+  if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  return (LCTF_INFO_KIND (fp, tp->ctt_info));
+}
+
+/* Return the kind (CTF_K_* constant) for the specified type ID.
+   Slices are considered to be of the same kind as the type sliced.  */
+
+int
+ctf_type_kind (ctf_file_t *fp, ctf_id_t type)
+{
+  int kind;
+
+  if ((kind = ctf_type_kind_unsliced (fp, type)) == CTF_ERR)
+    return CTF_ERR;
+
+  if (kind == CTF_K_SLICE)
+    {
+      if ((type = ctf_type_reference (fp, type)) == CTF_ERR)
+	return CTF_ERR;
+      kind = ctf_type_kind_unsliced (fp, type);
+    }
+
+  return kind;
+}
+
+/* If the type is one that directly references another type (such as POINTER),
+   then return the ID of the type to which it refers.  */
+
+ctf_id_t
+ctf_type_reference (ctf_file_t *fp, ctf_id_t type)
+{
+  ctf_file_t *ofp = fp;
+  const ctf_type_t *tp;
+
+  if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  switch (LCTF_INFO_KIND (fp, tp->ctt_info))
+    {
+    case CTF_K_POINTER:
+    case CTF_K_TYPEDEF:
+    case CTF_K_VOLATILE:
+    case CTF_K_CONST:
+    case CTF_K_RESTRICT:
+      return tp->ctt_type;
+      /* Slices store their type in an unusual place.  */
+    case CTF_K_SLICE:
+      {
+	const ctf_slice_t *sp;
+	ssize_t increment;
+	(void) ctf_get_ctt_size (fp, tp, NULL, &increment);
+	sp = (const ctf_slice_t *) ((uintptr_t) tp + increment);
+	return sp->cts_type;
+      }
+    default:
+      return (ctf_set_errno (ofp, ECTF_NOTREF));
+    }
+}
+
+/* Find a pointer to type by looking in fp->ctf_ptrtab.  If we can't find a
+   pointer to the given type, see if we can compute a pointer to the type
+   resulting from resolving the type down to its base type and use that
+   instead.  This helps with cases where the CTF data includes "struct foo *"
+   but not "foo_t *" and the user accesses "foo_t *" in the debugger.
+
+   XXX what about parent containers?  */
+
+ctf_id_t
+ctf_type_pointer (ctf_file_t *fp, ctf_id_t type)
+{
+  ctf_file_t *ofp = fp;
+  ctf_id_t ntype;
+
+  if (ctf_lookup_by_id (&fp, type) == NULL)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  if ((ntype = fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX (fp, type)]) != 0)
+    return (LCTF_INDEX_TO_TYPE (fp, ntype, (fp->ctf_flags & LCTF_CHILD)));
+
+  if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
+    return (ctf_set_errno (ofp, ECTF_NOTYPE));
+
+  if (ctf_lookup_by_id (&fp, type) == NULL)
+    return (ctf_set_errno (ofp, ECTF_NOTYPE));
+
+  if ((ntype = fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX (fp, type)]) != 0)
+    return (LCTF_INDEX_TO_TYPE (fp, ntype, (fp->ctf_flags & LCTF_CHILD)));
+
+  return (ctf_set_errno (ofp, ECTF_NOTYPE));
+}
+
+/* Return the encoding for the specified INTEGER or FLOAT.  */
+
+int
+ctf_type_encoding (ctf_file_t *fp, ctf_id_t type, ctf_encoding_t *ep)
+{
+  ctf_file_t *ofp = fp;
+  ctf_dtdef_t *dtd;
+  const ctf_type_t *tp;
+  ssize_t increment;
+  uint32_t data;
+
+  if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  if ((dtd = ctf_dynamic_type (ofp, type)) != NULL)
+    {
+      *ep = dtd->dtd_u.dtu_enc;
+      return 0;
+    }
+
+  (void) ctf_get_ctt_size (fp, tp, NULL, &increment);
+
+  switch (LCTF_INFO_KIND (fp, tp->ctt_info))
+    {
+    case CTF_K_INTEGER:
+      data = *(const uint32_t *) ((uintptr_t) tp + increment);
+      ep->cte_format = CTF_INT_ENCODING (data);
+      ep->cte_offset = CTF_INT_OFFSET (data);
+      ep->cte_bits = CTF_INT_BITS (data);
+      break;
+    case CTF_K_FLOAT:
+      data = *(const uint32_t *) ((uintptr_t) tp + increment);
+      ep->cte_format = CTF_FP_ENCODING (data);
+      ep->cte_offset = CTF_FP_OFFSET (data);
+      ep->cte_bits = CTF_FP_BITS (data);
+      break;
+    case CTF_K_SLICE:
+      {
+	const ctf_slice_t *slice;
+	ctf_encoding_t underlying_en;
+
+	slice = (ctf_slice_t *) ((uintptr_t) tp + increment);
+	data = ctf_type_encoding (fp, slice->cts_type, &underlying_en);
+
+	ep->cte_format = underlying_en.cte_format;
+	ep->cte_offset = slice->cts_offset;
+	ep->cte_bits = slice->cts_bits;
+	break;
+      }
+    default:
+      return (ctf_set_errno (ofp, ECTF_NOTINTFP));
+    }
+
+  return 0;
+}
+
+int
+ctf_type_cmp (ctf_file_t *lfp, ctf_id_t ltype, ctf_file_t *rfp,
+	      ctf_id_t rtype)
+{
+  int rval;
+
+  if (ltype < rtype)
+    rval = -1;
+  else if (ltype > rtype)
+    rval = 1;
+  else
+    rval = 0;
+
+  if (lfp == rfp)
+    return rval;
+
+  if (LCTF_TYPE_ISPARENT (lfp, ltype) && lfp->ctf_parent != NULL)
+    lfp = lfp->ctf_parent;
+
+  if (LCTF_TYPE_ISPARENT (rfp, rtype) && rfp->ctf_parent != NULL)
+    rfp = rfp->ctf_parent;
+
+  if (lfp < rfp)
+    return -1;
+
+  if (lfp > rfp)
+    return 1;
+
+  return rval;
+}
+
+/* Return a boolean value indicating if two types are compatible.  This function
+   returns true if the two types are the same, or if they (or their ultimate
+   base type) have the same encoding properties, or (for structs / unions /
+   enums / forward declarations) if they have the same name and (for structs /
+   unions) member count.  */
+
+int
+ctf_type_compat (ctf_file_t *lfp, ctf_id_t ltype,
+		 ctf_file_t *rfp, ctf_id_t rtype)
+{
+  const ctf_type_t *ltp, *rtp;
+  ctf_encoding_t le, re;
+  ctf_arinfo_t la, ra;
+  uint32_t lkind, rkind;
+  int same_names = 0;
+
+  if (ctf_type_cmp (lfp, ltype, rfp, rtype) == 0)
+    return 1;
+
+  ltype = ctf_type_resolve (lfp, ltype);
+  lkind = ctf_type_kind (lfp, ltype);
+
+  rtype = ctf_type_resolve (rfp, rtype);
+  rkind = ctf_type_kind (rfp, rtype);
+
+  ltp = ctf_lookup_by_id (&lfp, ltype);
+  rtp = ctf_lookup_by_id (&rfp, rtype);
+
+  if (ltp != NULL && rtp != NULL)
+    same_names = (strcmp (ctf_strptr (lfp, ltp->ctt_name),
+			  ctf_strptr (rfp, rtp->ctt_name)) == 0);
+
+  if (((lkind == CTF_K_ENUM) && (rkind == CTF_K_INTEGER)) ||
+      ((rkind == CTF_K_ENUM) && (lkind == CTF_K_INTEGER)))
+    return 1;
+
+  if (lkind != rkind)
+    return 0;
+
+  switch (lkind)
+    {
+    case CTF_K_INTEGER:
+    case CTF_K_FLOAT:
+      memset (&le, 0, sizeof (le));
+      memset (&re, 0, sizeof (re));
+      return (ctf_type_encoding (lfp, ltype, &le) == 0
+	      && ctf_type_encoding (rfp, rtype, &re) == 0
+	      && memcmp (&le, &re, sizeof (ctf_encoding_t)) == 0);
+    case CTF_K_POINTER:
+      return (ctf_type_compat (lfp, ctf_type_reference (lfp, ltype),
+			       rfp, ctf_type_reference (rfp, rtype)));
+    case CTF_K_ARRAY:
+      return (ctf_array_info (lfp, ltype, &la) == 0
+	      && ctf_array_info (rfp, rtype, &ra) == 0
+	      && la.ctr_nelems == ra.ctr_nelems
+	      && ctf_type_compat (lfp, la.ctr_contents, rfp, ra.ctr_contents)
+	      && ctf_type_compat (lfp, la.ctr_index, rfp, ra.ctr_index));
+    case CTF_K_STRUCT:
+    case CTF_K_UNION:
+      return (same_names && (ctf_type_size (lfp, ltype)
+			     == ctf_type_size (rfp, rtype)));
+    case CTF_K_ENUM:
+      {
+	int lencoded, rencoded;
+	lencoded = ctf_type_encoding (lfp, ltype, &le);
+	rencoded = ctf_type_encoding (rfp, rtype, &re);
+
+	if ((lencoded != rencoded) ||
+	    ((lencoded == 0) && memcmp (&le, &re, sizeof (ctf_encoding_t)) != 0))
+	  return 0;
+      }
+      /* FALLTHRU */
+    case CTF_K_FORWARD:
+      return same_names;   /* No other checks required for these type kinds.  */
+    default:
+      return 0;		      /* Should not get here since we did a resolve.  */
+    }
+}
+
+/* Return the type and offset for a given member of a STRUCT or UNION.  */
+
+int
+ctf_member_info (ctf_file_t *fp, ctf_id_t type, const char *name,
+		 ctf_membinfo_t *mip)
+{
+  ctf_file_t *ofp = fp;
+  const ctf_type_t *tp;
+  ssize_t size, increment;
+  uint32_t kind, n;
+
+  if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  (void) ctf_get_ctt_size (fp, tp, &size, &increment);
+  kind = LCTF_INFO_KIND (fp, tp->ctt_info);
+
+  if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
+    return (ctf_set_errno (ofp, ECTF_NOTSOU));
+
+  if (size < CTF_LSTRUCT_THRESH)
+    {
+      const ctf_member_t *mp = (const ctf_member_t *) ((uintptr_t) tp +
+						       increment);
+
+      for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, mp++)
+	{
+	  if (strcmp (ctf_strptr (fp, mp->ctm_name), name) == 0)
+	    {
+	      mip->ctm_type = mp->ctm_type;
+	      mip->ctm_offset = mp->ctm_offset;
+	      return 0;
+	    }
+	}
+    }
+  else
+    {
+      const ctf_lmember_t *lmp = (const ctf_lmember_t *) ((uintptr_t) tp +
+							  increment);
+
+      for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, lmp++)
+	{
+	  if (strcmp (ctf_strptr (fp, lmp->ctlm_name), name) == 0)
+	    {
+	      mip->ctm_type = lmp->ctlm_type;
+	      mip->ctm_offset = (unsigned long) CTF_LMEM_OFFSET (lmp);
+	      return 0;
+	    }
+	}
+    }
+
+  return (ctf_set_errno (ofp, ECTF_NOMEMBNAM));
+}
+
+/* Return the array type, index, and size information for the specified ARRAY.  */
+
+int
+ctf_array_info (ctf_file_t *fp, ctf_id_t type, ctf_arinfo_t *arp)
+{
+  ctf_file_t *ofp = fp;
+  const ctf_type_t *tp;
+  const ctf_array_t *ap;
+  const ctf_dtdef_t *dtd;
+  ssize_t increment;
+
+  if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  if (LCTF_INFO_KIND (fp, tp->ctt_info) != CTF_K_ARRAY)
+    return (ctf_set_errno (ofp, ECTF_NOTARRAY));
+
+  if ((dtd = ctf_dynamic_type (ofp, type)) != NULL)
+    {
+      *arp = dtd->dtd_u.dtu_arr;
+      return 0;
+    }
+
+  (void) ctf_get_ctt_size (fp, tp, NULL, &increment);
+
+  ap = (const ctf_array_t *) ((uintptr_t) tp + increment);
+  arp->ctr_contents = ap->cta_contents;
+  arp->ctr_index = ap->cta_index;
+  arp->ctr_nelems = ap->cta_nelems;
+
+  return 0;
+}
+
+/* Convert the specified value to the corresponding enum tag name, if a
+   matching name can be found.  Otherwise NULL is returned.  */
+
+const char *
+ctf_enum_name (ctf_file_t *fp, ctf_id_t type, int value)
+{
+  ctf_file_t *ofp = fp;
+  const ctf_type_t *tp;
+  const ctf_enum_t *ep;
+  ssize_t increment;
+  uint32_t n;
+
+  if ((type = ctf_type_resolve_unsliced (fp, type)) == CTF_ERR)
+    return NULL;		/* errno is set for us.  */
+
+  if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
+    return NULL;		/* errno is set for us.  */
+
+  if (LCTF_INFO_KIND (fp, tp->ctt_info) != CTF_K_ENUM)
+    {
+      (void) ctf_set_errno (ofp, ECTF_NOTENUM);
+      return NULL;
+    }
+
+  (void) ctf_get_ctt_size (fp, tp, NULL, &increment);
+
+  ep = (const ctf_enum_t *) ((uintptr_t) tp + increment);
+
+  for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, ep++)
+    {
+      if (ep->cte_value == value)
+	return (ctf_strptr (fp, ep->cte_name));
+    }
+
+  (void) ctf_set_errno (ofp, ECTF_NOENUMNAM);
+  return NULL;
+}
+
+/* Convert the specified enum tag name to the corresponding value, if a
+   matching name can be found.  Otherwise CTF_ERR is returned.  */
+
+int
+ctf_enum_value (ctf_file_t * fp, ctf_id_t type, const char *name, int *valp)
+{
+  ctf_file_t *ofp = fp;
+  const ctf_type_t *tp;
+  const ctf_enum_t *ep;
+  ssize_t increment;
+  uint32_t n;
+
+  if ((type = ctf_type_resolve_unsliced (fp, type)) == CTF_ERR)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  if (LCTF_INFO_KIND (fp, tp->ctt_info) != CTF_K_ENUM)
+    {
+      (void) ctf_set_errno (ofp, ECTF_NOTENUM);
+      return CTF_ERR;
+    }
+
+  (void) ctf_get_ctt_size (fp, tp, NULL, &increment);
+
+  ep = (const ctf_enum_t *) ((uintptr_t) tp + increment);
+
+  for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, ep++)
+    {
+      if (strcmp (ctf_strptr (fp, ep->cte_name), name) == 0)
+	{
+	  if (valp != NULL)
+	    *valp = ep->cte_value;
+	  return 0;
+	}
+    }
+
+  (void) ctf_set_errno (ofp, ECTF_NOENUMNAM);
+  return CTF_ERR;
+}
+
+/* Recursively visit the members of any type.  This function is used as the
+   engine for ctf_type_visit, below.  We resolve the input type, recursively
+   invoke ourself for each type member if the type is a struct or union, and
+   then invoke the callback function on the current type.  If any callback
+   returns non-zero, we abort and percolate the error code back up to the top.  */
+
+static int
+ctf_type_rvisit (ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func,
+		 void *arg, const char *name, unsigned long offset, int depth)
+{
+  ctf_id_t otype = type;
+  const ctf_type_t *tp;
+  ssize_t size, increment;
+  uint32_t kind, n;
+  int rc;
+
+  if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  if ((rc = func (name, otype, offset, depth, arg)) != 0)
+    return rc;
+
+  kind = LCTF_INFO_KIND (fp, tp->ctt_info);
+
+  if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
+    return 0;
+
+  (void) ctf_get_ctt_size (fp, tp, &size, &increment);
+
+  if (size < CTF_LSTRUCT_THRESH)
+    {
+      const ctf_member_t *mp = (const ctf_member_t *) ((uintptr_t) tp +
+						       increment);
+
+      for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, mp++)
+	{
+	  if ((rc = ctf_type_rvisit (fp, mp->ctm_type,
+				     func, arg, ctf_strptr (fp, mp->ctm_name),
+				     offset + mp->ctm_offset,
+				     depth + 1)) != 0)
+	    return rc;
+	}
+
+    }
+  else
+    {
+      const ctf_lmember_t *lmp = (const ctf_lmember_t *) ((uintptr_t) tp +
+							  increment);
+
+      for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, lmp++)
+	{
+	  if ((rc = ctf_type_rvisit (fp, lmp->ctlm_type,
+				     func, arg, ctf_strptr (fp,
+							    lmp->ctlm_name),
+				     offset + (unsigned long) CTF_LMEM_OFFSET (lmp),
+				     depth + 1)) != 0)
+	    return rc;
+	}
+    }
+
+  return 0;
+}
+
+/* Recursively visit the members of any type.  We pass the name, member
+ type, and offset of each member to the specified callback function.  */
+int
+ctf_type_visit (ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg)
+{
+  return (ctf_type_rvisit (fp, type, func, arg, "", 0, 0));
+}
-- 
2.21.0.237.gd0cfaa883d

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v2 16/19] libctf: labels
  2019-05-17 22:10 [PATCH v2 00/19] libctf, and CTF support for objdump and readelf Nick Alcock
                   ` (16 preceding siblings ...)
  2019-05-17 22:11 ` [PATCH v2 18/19] libctf: build system Nick Alcock
@ 2019-05-17 22:12 ` Nick Alcock
  2019-05-17 22:12 ` [PATCH v2 11/19] libctf: core type lookup Nick Alcock
                   ` (2 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nick Alcock @ 2019-05-17 22:12 UTC (permalink / raw)
  To: binutils

This facility allows you to associate regions of type IDs with *labels*,
a labelled tiling of the type ID space. You can use these to define
CTF containers with distinct parents for distinct ranges of the ID
space, or to assist with parallelization of CTF processing, or for any
other purpose you can think of.

Notably absent from here (though declared in the API header) is any way
to define new labels: this will probably be introduced soon, as part of
the linker deduplication work.  (One existed in the past, but was deeply
tied to the Solaris CTF file generator and had to be torn out.)

I would be happy to drop this entire commit for now as half-baked, but
it's an ancient interface and so to some degree shows what the original
designers of CTF thought you could do with it.

Changes from v1:
 - Correct erroneous license (GPLv2+ -> v3+) and reset copyright years.

libctf/
	* ctf-labels.c: New.
include/
	* ctf-api.h (ctf_label_f): New.
	(ctf_label_set): New.
	(ctf_label_get): New.
	(ctf_label_topmost): New.
	(ctf_label_info): New.
	(ctf_label_iter): New.
---
 include/ctf-api.h   |   9 +++
 libctf/ctf-labels.c | 138 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 147 insertions(+)
 create mode 100644 libctf/ctf-labels.c

diff --git a/include/ctf-api.h b/include/ctf-api.h
index 6d6efdd513..14a61520bb 100644
--- a/include/ctf-api.h
+++ b/include/ctf-api.h
@@ -213,6 +213,8 @@ typedef int ctf_member_f (const char *name, ctf_id_t membtype,
 typedef int ctf_enum_f (const char *name, int val, void *arg);
 typedef int ctf_variable_f (const char *name, ctf_id_t type, void *arg);
 typedef int ctf_type_f (ctf_id_t type, void *arg);
+typedef int ctf_label_f (const char *name, const ctf_lblinfo_t *info,
+			 void *arg);
 typedef int ctf_archive_member_f (ctf_file_t *fp, const char *name, void *arg);
 typedef int ctf_archive_raw_member_f (const char *name, const void *content,
 				      size_t len, void *arg);
@@ -279,9 +281,16 @@ extern int ctf_array_info (ctf_file_t *, ctf_id_t, ctf_arinfo_t *);
 extern const char *ctf_enum_name (ctf_file_t *, ctf_id_t, int);
 extern int ctf_enum_value (ctf_file_t *, ctf_id_t, const char *, int *);
 
+extern void ctf_label_set (ctf_file_t *, const char *);
+extern const char *ctf_label_get (ctf_file_t *);
+
+extern const char *ctf_label_topmost (ctf_file_t *);
+extern int ctf_label_info (ctf_file_t *, const char *, ctf_lblinfo_t *);
+
 extern int ctf_member_iter (ctf_file_t *, ctf_id_t, ctf_member_f *, void *);
 extern int ctf_enum_iter (ctf_file_t *, ctf_id_t, ctf_enum_f *, void *);
 extern int ctf_type_iter (ctf_file_t *, ctf_type_f *, void *);
+extern int ctf_label_iter (ctf_file_t *, ctf_label_f *, void *);
 extern int ctf_variable_iter (ctf_file_t *, ctf_variable_f *, void *);
 extern int ctf_archive_iter (const ctf_archive_t *, ctf_archive_member_f *,
 			     void *);
diff --git a/libctf/ctf-labels.c b/libctf/ctf-labels.c
new file mode 100644
index 0000000000..9b9fffea4e
--- /dev/null
+++ b/libctf/ctf-labels.c
@@ -0,0 +1,138 @@
+/* Labelled ranges of type IDs.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+
+   This file is part of libctf.
+
+   libctf is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+   See the GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <ctf-impl.h>
+#include <string.h>
+
+static int
+extract_label_info (ctf_file_t *fp, const ctf_lblent_t **ctl,
+		    uint32_t *num_labels)
+{
+  const ctf_header_t *h;
+
+  h = (const ctf_header_t *) fp->ctf_data.cts_data;
+
+  *ctl = (const ctf_lblent_t *) (fp->ctf_buf + h->cth_lbloff);
+  *num_labels = (h->cth_objtoff - h->cth_lbloff) / sizeof (ctf_lblent_t);
+
+  return 0;
+}
+
+/* Returns the topmost label, or NULL if any errors are encountered.  */
+
+const char *
+ctf_label_topmost (ctf_file_t *fp)
+{
+  const ctf_lblent_t *ctlp = NULL;
+  const char *s;
+  uint32_t num_labels = 0;
+
+  if (extract_label_info (fp, &ctlp, &num_labels) == CTF_ERR)
+    return NULL;				/* errno is set for us.  */
+
+  if (num_labels == 0)
+    {
+      (void) ctf_set_errno (fp, ECTF_NOLABELDATA);
+      return NULL;
+    }
+
+  if ((s = ctf_strraw (fp, (ctlp + num_labels - 1)->ctl_label)) == NULL)
+    (void) ctf_set_errno (fp, ECTF_CORRUPT);
+
+  return s;
+}
+
+/* Iterate over all labels.  We pass the label string and the lblinfo_t struct
+   to the specified callback function.  */
+int
+ctf_label_iter (ctf_file_t *fp, ctf_label_f *func, void *arg)
+{
+  const ctf_lblent_t *ctlp = NULL;
+  uint32_t i;
+  uint32_t num_labels = 0;
+  ctf_lblinfo_t linfo;
+  const char *lname;
+  int rc;
+
+  if (extract_label_info (fp, &ctlp, &num_labels) == CTF_ERR)
+    return CTF_ERR;		/* errno is set for us.  */
+
+  if (num_labels == 0)
+    return (ctf_set_errno (fp, ECTF_NOLABELDATA));
+
+  for (i = 0; i < num_labels; i++, ctlp++)
+    {
+      if ((lname = ctf_strraw (fp, ctlp->ctl_label)) == NULL)
+	{
+	  ctf_dprintf ("failed to decode label %u with "
+		       "type %u\n", ctlp->ctl_label, ctlp->ctl_type);
+	  return (ctf_set_errno (fp, ECTF_CORRUPT));
+	}
+
+      linfo.ctb_type = ctlp->ctl_type;
+      if ((rc = func (lname, &linfo, arg)) != 0)
+	return rc;
+    }
+
+  return 0;
+}
+
+typedef struct linfo_cb_arg
+{
+  const char *lca_name;		/* Label we want to retrieve info for.  */
+  ctf_lblinfo_t *lca_info;	/* Where to store the info about the label.  */
+} linfo_cb_arg_t;
+
+static int
+label_info_cb (const char *lname, const ctf_lblinfo_t *linfo, void *arg)
+{
+  /* If lname matches the label we are looking for, copy the
+    lblinfo_t struct for the caller.  */
+
+  if (strcmp (lname, ((linfo_cb_arg_t *) arg)->lca_name) == 0)
+    {
+      /* * Allow caller not to allocate storage to test if label exists.  */
+
+      if (((linfo_cb_arg_t *) arg)->lca_info != NULL)
+	memcpy (((linfo_cb_arg_t *) arg)->lca_info, linfo,
+	       sizeof (ctf_lblinfo_t));
+      return 1;		/* Indicate we found a match.  */
+    }
+
+  return 0;
+}
+
+/* Retrieve information about the label with name "lname". */
+int
+ctf_label_info (ctf_file_t *fp, const char *lname, ctf_lblinfo_t *linfo)
+{
+  linfo_cb_arg_t cb_arg;
+  int rc;
+
+  cb_arg.lca_name = lname;
+  cb_arg.lca_info = linfo;
+
+  if ((rc = ctf_label_iter (fp, label_info_cb, &cb_arg)) == CTF_ERR)
+    return rc;
+
+  if (rc != 1)
+    return (ctf_set_errno (fp, ECTF_NOLABEL));
+
+  return 0;
+}
-- 
2.21.0.237.gd0cfaa883d

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v2 00/19] libctf, and CTF support for objdump and readelf
  2019-05-17 22:10 [PATCH v2 00/19] libctf, and CTF support for objdump and readelf Nick Alcock
                   ` (18 preceding siblings ...)
  2019-05-17 22:12 ` [PATCH v2 11/19] libctf: core type lookup Nick Alcock
@ 2019-05-20 19:27 ` Joseph Myers
  2019-05-20 20:50   ` Nick Alcock
  2019-05-28  8:33 ` Nick Clifton
  20 siblings, 1 reply; 31+ messages in thread
From: Joseph Myers @ 2019-05-20 19:27 UTC (permalink / raw)
  To: Nick Alcock; +Cc: binutils

On Fri, 17 May 2019, Nick Alcock wrote:

> Joseph: you'll probably be interested in patches 3, 9, 10, and 15 in particular,
> for their BFDization and portability fixes.

Thanks.  A quick question would be what hosts you've tested this builds 
for.  At least some GNU/Linux distributions package cross-compilers for 
MinGW; if you install such a compiler and make sure that binutils, with 
these patches, can build using it, --host=x86_64-w64-mingw32 
--target=<some ELF target> (adjust host as needed if the host triplet of 
the packaged compiler is different), then there shouldn't be major 
problems getting it to build on any other likely host either.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v2 00/19] libctf, and CTF support for objdump and readelf
  2019-05-20 19:27 ` [PATCH v2 00/19] libctf, and CTF support for objdump and readelf Joseph Myers
@ 2019-05-20 20:50   ` Nick Alcock
  0 siblings, 0 replies; 31+ messages in thread
From: Nick Alcock @ 2019-05-20 20:50 UTC (permalink / raw)
  To: Joseph Myers; +Cc: binutils

On 20 May 2019, Joseph Myers uttered the following:

> On Fri, 17 May 2019, Nick Alcock wrote:
>
>> Joseph: you'll probably be interested in patches 3, 9, 10, and 15 in particular,
>> for their BFDization and portability fixes.
>
> Thanks.  A quick question would be what hosts you've tested this builds 
> for.  At least some GNU/Linux distributions package cross-compilers for 
> MinGW; if you install such a compiler and make sure that binutils, with 
> these patches, can build using it, --host=x86_64-w64-mingw32 
> --target=<some ELF target> (adjust host as needed if the host triplet of 
> the packaged compiler is different), then there shouldn't be major 
> problems getting it to build on any other likely host either.

Oh blast I knew I forgot to mention something.

This has mostly been tested on Linux (x86_64, arm64, and sparc64): I did
do a native mingw build a while back (right after doing the mmap and
pread stuff) but I probably need to do another one. I'm tempted to do a
FreeBSD build too simply because it's easy.

I did most of the no-mmap and no-pread() testing on Linux, by just
hacking the config.h to turn it off and making sure it wasn't making the
relevant syscalls any more, and still worked. (Which it does, but it's
slower when doing archive opens, unsurprisingly, since it's reading the
whole archive in even if only a bit is needed.)

I suspect the bfd side of things is still broken: a teammate has just
tested it and reported that things aren't working there yet. I'll look
at that tomorrow.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v2 00/19] libctf, and CTF support for objdump and readelf
  2019-05-17 22:10 [PATCH v2 00/19] libctf, and CTF support for objdump and readelf Nick Alcock
                   ` (19 preceding siblings ...)
  2019-05-20 19:27 ` [PATCH v2 00/19] libctf, and CTF support for objdump and readelf Joseph Myers
@ 2019-05-28  8:33 ` Nick Clifton
  2019-05-28  9:56   ` Nick Alcock
  2019-05-28 16:39   ` Jose E. Marchesi
  20 siblings, 2 replies; 31+ messages in thread
From: Nick Clifton @ 2019-05-28  8:33 UTC (permalink / raw)
  To: Nick Alcock, binutils

Hi Nick,

  Sorry for the delay in reviewing.
 
> Nick Alcock (19):
>   include: new header ctf.h: file format description
>   include: new header ctf-api.h
>   libctf: lowest-level memory allocation and debug-dumping wrappers
>   libctf: low-level list manipulation and helper utilities
>   libctf: error handling
>   libctf: hashing
>   libctf: implementation definitions related to file creation
>   libctf: creation functions
>   libctf: opening
>   libctf: ELF file opening via BFD
>   libctf: core type lookup
>   libctf: lookups by name and symbol
>   libctf: type copying
>   libctf: library version enforcement
>   libctf: mmappable archives
>   libctf: labels
>   libctf: debug dumping
>   libctf: build system
>   binutils: CTF support for objdump and readelf

Patch series approved (all of it) - please apply.

I would however ask that you make two small additions:

  * Please could you add an entry to the binutils/NEWS file,
    mentioning this new feature of the binutils.

  * Please could you add an entry to the binutils/MAINTAINERS
    file, listing yourself, or someone else at Oracle, as the
    maintainer for the CTF code.

Thanks very much for contributing this code to the binutils project.

Cheers
  Nick

 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v2 00/19] libctf, and CTF support for objdump and readelf
  2019-05-28  8:33 ` Nick Clifton
@ 2019-05-28  9:56   ` Nick Alcock
  2019-05-28 16:39   ` Jose E. Marchesi
  1 sibling, 0 replies; 31+ messages in thread
From: Nick Alcock @ 2019-05-28  9:56 UTC (permalink / raw)
  To: Nick Clifton; +Cc: binutils, Jose E. Marchesi

On 28 May 2019, Nick Clifton verbalised:

> Hi Nick,
>
>   Sorry for the delay in reviewing.

No problem! Review bandwidth is scarce: I'm happy to get reviews at all.

>> Nick Alcock (19):
>>   include: new header ctf.h: file format description
>>   include: new header ctf-api.h
>>   libctf: lowest-level memory allocation and debug-dumping wrappers
>>   libctf: low-level list manipulation and helper utilities
>>   libctf: error handling
>>   libctf: hashing
>>   libctf: implementation definitions related to file creation
>>   libctf: creation functions
>>   libctf: opening
>>   libctf: ELF file opening via BFD
>>   libctf: core type lookup
>>   libctf: lookups by name and symbol
>>   libctf: type copying
>>   libctf: library version enforcement
>>   libctf: mmappable archives
>>   libctf: labels
>>   libctf: debug dumping
>>   libctf: build system
>>   binutils: CTF support for objdump and readelf
>
> Patch series approved (all of it) - please apply.

Thank you! -- though I don't have commit rights yet, so until someone
sees fit to grant me that someone else will have to do the actual push.
I also don't really know how one transforms the ChangeLogs in the commit
messages into actual ChangeLog files in the commits: do you really edit
every commit and add the ChangeLog changes to it by hand?

(I should of course rebase it first so it's not based on a months-old
checkout, and make sure that it still works after the rebase.)


On related matters: I presume nobody minds if I submit further
improvements that change the format to provide size reductions (quite
radical ones)? i.e. nobody minds if it's not set in stone yet? It's
still young in this form, after all.

For backward-compatibility, I propose to use the usual GNU rules, and
provide backward-compat for all formats "in the world" in any official
release version: so for now I'll keep the format version at v3 and any
format changes go into that, updating the v1/v2 -> v3 compat code at the
same time, until a release of GCC or the not-yet-written linker plugin
or *something* that generates CTF, whereupon the format is bumped to v4
and backward-compat code for v3 -> all future changes in v4 need to be
added as part of any future changes. The backward-compat stuff also
means that most things that generate CTF don't need to change when the
format changes: the linker plugin will bring the format up to date as
needed.

(As for something that generates CTF, the linker plugin is my next major
thing to attack. I'm just trying to shrink things a little first. It's
amazing how many obvious improvements show up when you get your code
properly reviewed.)

> I would however ask that you make two small additions:
>
>   * Please could you add an entry to the binutils/NEWS file,
>     mentioning this new feature of the binutils.

How's about

 * Add support for dumping types encoded in the Compact Type Format
   to objdump and readelf.

(Should we mention that this is a *new* CTF, not format-compatible with
existing ones? Should we mention that we haven't committed tools that
emit CTF yet? Should we mention the existence of the library itself
anywhere, even though it's not -- yet -- user-visible? I'm not sure.)

>   * Please could you add an entry to the binutils/MAINTAINERS
>     file, listing yourself, or someone else at Oracle, as the
>     maintainer for the CTF code.

Of course! Though, again, without commit access all I can do is propose
an entry for the top level and an entry for binutils/MAINTAINERS, which
may change if GCC portions of this get in.

The top-level entry gets added to

bfd/; binutils/; elfcpp/; gas/; gold/; gprof/; ld/; opcodes/; cpu/;

I think. For MAINTAINERS, I am happy to have added

CTF		Nick Alcock <nick.alcock@oracle.com>

> Thanks very much for contributing this code to the binutils project.

I'm not done yet! Though the linker plugin won't turn up immediately
since I still have to write it, it will turn up, and this stuff will
actually be useful. (I'll be doing a simple linker plugin without
deduplication first, and then adding deduplication.)

But this is the foundation. Nothing else is possible without it. So
thank you for the excellent review!

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v2 00/19] libctf, and CTF support for objdump and readelf
  2019-05-28  8:33 ` Nick Clifton
  2019-05-28  9:56   ` Nick Alcock
@ 2019-05-28 16:39   ` Jose E. Marchesi
  2019-05-28 19:16     ` Christophe Lyon
  1 sibling, 1 reply; 31+ messages in thread
From: Jose E. Marchesi @ 2019-05-28 16:39 UTC (permalink / raw)
  To: Nick Clifton; +Cc: Nick Alcock, binutils


    > Nick Alcock (19):
    >   include: new header ctf.h: file format description
    >   include: new header ctf-api.h
    >   libctf: lowest-level memory allocation and debug-dumping wrappers
    >   libctf: low-level list manipulation and helper utilities
    >   libctf: error handling
    >   libctf: hashing
    >   libctf: implementation definitions related to file creation
    >   libctf: creation functions
    >   libctf: opening
    >   libctf: ELF file opening via BFD
    >   libctf: core type lookup
    >   libctf: lookups by name and symbol
    >   libctf: type copying
    >   libctf: library version enforcement
    >   libctf: mmappable archives
    >   libctf: labels
    >   libctf: debug dumping
    >   libctf: build system
    >   binutils: CTF support for objdump and readelf
    
    Patch series approved (all of it) - please apply.

Just pushed it in behalf of Nix, with the additions you suggested.
Thanks!

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v2 00/19] libctf, and CTF support for objdump and readelf
  2019-05-28 16:39   ` Jose E. Marchesi
@ 2019-05-28 19:16     ` Christophe Lyon
  2019-05-28 21:36       ` Nix
  0 siblings, 1 reply; 31+ messages in thread
From: Christophe Lyon @ 2019-05-28 19:16 UTC (permalink / raw)
  To: Jose E. Marchesi; +Cc: Nick Clifton, Nick Alcock, binutils

Hi,


On Tue, 28 May 2019 at 18:39, Jose E. Marchesi <jose.marchesi@oracle.com> wrote:
>
>
>     > Nick Alcock (19):
>     >   include: new header ctf.h: file format description
>     >   include: new header ctf-api.h
>     >   libctf: lowest-level memory allocation and debug-dumping wrappers
>     >   libctf: low-level list manipulation and helper utilities
>     >   libctf: error handling
>     >   libctf: hashing
>     >   libctf: implementation definitions related to file creation
>     >   libctf: creation functions
>     >   libctf: opening
>     >   libctf: ELF file opening via BFD
>     >   libctf: core type lookup
>     >   libctf: lookups by name and symbol
>     >   libctf: type copying
>     >   libctf: library version enforcement
>     >   libctf: mmappable archives
>     >   libctf: labels
>     >   libctf: debug dumping
>     >   libctf: build system
>     >   binutils: CTF support for objdump and readelf
>
>     Patch series approved (all of it) - please apply.
>
> Just pushed it in behalf of Nix, with the additions you suggested.
> Thanks!


One of the patches in the series broke the build for --target arm-pe:
../libctf/libctf.a(ctf-open-bfd.o): In function `ctf_bfdopen_ctfsect':
/home/tcwg-buildslave/workspace/tcwg-binutils/bfd/--enable-64-bit-bfd=no/label/tcwg-x86_64-cam/target/arm-pe/build-arm-pe/libctf/../../libctf/ctf-open-bfd.c:136:
undefined reference to `bfd_section_from_elf_index'
/home/tcwg-buildslave/workspace/tcwg-binutils/bfd/--enable-64-bit-bfd=no/label/tcwg-x86_64-cam/target/arm-pe/build-arm-pe/libctf/../../libctf/ctf-open-bfd.c:145:
undefined reference to `bfd_section_from_elf_index'

Can you check & fix?

Thanks

Christophe

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v2 00/19] libctf, and CTF support for objdump and readelf
  2019-05-28 19:16     ` Christophe Lyon
@ 2019-05-28 21:36       ` Nix
  2019-05-29  3:25         ` Alan Modra
  0 siblings, 1 reply; 31+ messages in thread
From: Nix @ 2019-05-28 21:36 UTC (permalink / raw)
  To: Christophe Lyon; +Cc: Jose E. Marchesi, Nick Clifton, binutils

On 28 May 2019, Christophe Lyon stated:

> On Tue, 28 May 2019 at 18:39, Jose E. Marchesi <jose.marchesi@oracle.com> wrote:
>>
>>
>>     > Nick Alcock (19):
>>     >   include: new header ctf.h: file format description
>>     >   include: new header ctf-api.h
>>     >   libctf: lowest-level memory allocation and debug-dumping wrappers
>>     >   libctf: low-level list manipulation and helper utilities
>>     >   libctf: error handling
>>     >   libctf: hashing
>>     >   libctf: implementation definitions related to file creation
>>     >   libctf: creation functions
>>     >   libctf: opening
>>     >   libctf: ELF file opening via BFD
>>     >   libctf: core type lookup
>>     >   libctf: lookups by name and symbol
>>     >   libctf: type copying
>>     >   libctf: library version enforcement
>>     >   libctf: mmappable archives
>>     >   libctf: labels
>>     >   libctf: debug dumping
>>     >   libctf: build system
>>     >   binutils: CTF support for objdump and readelf
>>
>>     Patch series approved (all of it) - please apply.
>>
>> Just pushed it in behalf of Nix, with the additions you suggested.
>> Thanks!
>
>
> One of the patches in the series broke the build for --target arm-pe:
> ../libctf/libctf.a(ctf-open-bfd.o): In function `ctf_bfdopen_ctfsect':
> /home/tcwg-buildslave/workspace/tcwg-binutils/bfd/--enable-64-bit-bfd=no/label/tcwg-x86_64-cam/target/arm-pe/build-arm-pe/libctf/../../libctf/ctf-open-bfd.c:136:
> undefined reference to `bfd_section_from_elf_index'
> /home/tcwg-buildslave/workspace/tcwg-binutils/bfd/--enable-64-bit-bfd=no/label/tcwg-x86_64-cam/target/arm-pe/build-arm-pe/libctf/../../libctf/ctf-open-bfd.c:145:
> undefined reference to `bfd_section_from_elf_index'
>
> Can you check & fix?

Very sorry about that. My non-ELF platform of choice was mingw, which I
now see pulls in the ELF bfd stuff! Ironically I had all the necessary
ifdefs in place for the non-ELF builds but was intentionally trimming
them out of the copy synced to binutils...

I am testing the fix below (on lots more targets, this time, so it might
be a few hours). I hope the build system fiddling is right. It was... a
bit counterintuitive, although all the changes made sense in hindsight.

I tested mingw, x86_64-pc-linux-gnu and arm-pe by hand and it seems to
work on all three.

commit e23cfedad4f85235337d485b5c51bdcda92565ef
Author: Nick Alcock <nick.alcock@oracle.com>
Date:   Tue May 28 22:24:01 2019 +0100

    Fix libctf build on non-ELF targets.
    
    All machinery works as on ELF, except for automatic loading of ELF
    string and symbol tables in the BFD-style open machinery.
    
            * Makefile.def (dependencies): configure-libctf depends on all-bfd
            and all its deps.
            * Makefile.in: Regenerated.
    
    libctf/
            * configure.in: Check for bfd_section_from_elf_index.
            * configure: Regenerate.
            * config.h.in [HAVE_BFD_ELF]: Likewise.
            * libctf/ctf_open_bfd (ctf_bfdopen_ctfsect): Use it.
            abfd is potentially unused now.

diff --git a/ChangeLog b/ChangeLog
index f57f4fe2f9..cbfb2155c2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2019-05-28  Nick Alcock  <nick.alcock@oracle.com>
+
+	* Makefile.def (dependencies): configure-libctf depends on all-bfd
+	and all its deps.
+	* Makefile.in: Regenerated.
+
 2019-05-28  Nick Alcock  <nick.alcock@oracle.com>
 
 	* MAINTAINERS: Add libctf.
diff --git a/Makefile.def b/Makefile.def
index 3aa03b45d3..e3a94f2c7d 100644
--- a/Makefile.def
+++ b/Makefile.def
@@ -522,6 +522,11 @@ dependencies = { module=all-fastjar; on=all-libiberty; };
 dependencies = { module=all-libctf; on=all-libiberty; hard=true; };
 dependencies = { module=all-libctf; on=all-bfd; };
 dependencies = { module=all-libctf; on=all-zlib; };
+// So that checking for ELF support in BFD from libctf configure is possible.
+dependencies = { module=configure-libctf; on=all-bfd; };
+dependencies = { module=configure-libctf; on=all-intl; };
+dependencies = { module=configure-libctf; on=all-zlib; };
+dependencies = { module=configure-libctf; on=all-libiconv; };
 
 // Warning, these are not well tested.
 dependencies = { module=all-bison; on=all-intl; };
diff --git a/Makefile.in b/Makefile.in
index 68675f0479..e4b6051b1a 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -50930,6 +50930,34 @@ all-stage3-libctf: maybe-all-stage3-zlib
 all-stage4-libctf: maybe-all-stage4-zlib
 all-stageprofile-libctf: maybe-all-stageprofile-zlib
 all-stagefeedback-libctf: maybe-all-stagefeedback-zlib
+configure-libctf: maybe-all-bfd
+configure-stage1-libctf: maybe-all-stage1-bfd
+configure-stage2-libctf: maybe-all-stage2-bfd
+configure-stage3-libctf: maybe-all-stage3-bfd
+configure-stage4-libctf: maybe-all-stage4-bfd
+configure-stageprofile-libctf: maybe-all-stageprofile-bfd
+configure-stagefeedback-libctf: maybe-all-stagefeedback-bfd
+configure-libctf: maybe-all-intl
+configure-stage1-libctf: maybe-all-stage1-intl
+configure-stage2-libctf: maybe-all-stage2-intl
+configure-stage3-libctf: maybe-all-stage3-intl
+configure-stage4-libctf: maybe-all-stage4-intl
+configure-stageprofile-libctf: maybe-all-stageprofile-intl
+configure-stagefeedback-libctf: maybe-all-stagefeedback-intl
+configure-libctf: maybe-all-zlib
+configure-stage1-libctf: maybe-all-stage1-zlib
+configure-stage2-libctf: maybe-all-stage2-zlib
+configure-stage3-libctf: maybe-all-stage3-zlib
+configure-stage4-libctf: maybe-all-stage4-zlib
+configure-stageprofile-libctf: maybe-all-stageprofile-zlib
+configure-stagefeedback-libctf: maybe-all-stagefeedback-zlib
+configure-libctf: maybe-all-libiconv
+configure-stage1-libctf: maybe-all-stage1-libiconv
+configure-stage2-libctf: maybe-all-stage2-libiconv
+configure-stage3-libctf: maybe-all-stage3-libiconv
+configure-stage4-libctf: maybe-all-stage4-libiconv
+configure-stageprofile-libctf: maybe-all-stageprofile-libiconv
+configure-stagefeedback-libctf: maybe-all-stagefeedback-libiconv
 all-bison: maybe-all-build-texinfo
 all-flex: maybe-all-build-bison
 all-flex: maybe-all-m4
diff --git a/libctf/ChangeLog b/libctf/ChangeLog
index a4fd3b17ba..879aeed38f 100644
--- a/libctf/ChangeLog
+++ b/libctf/ChangeLog
@@ -1,3 +1,11 @@
+2019-05-28  Nick Alcock  <nick.alcock@oracle.com>
+
+	* configure.in: Check for bfd_section_from_elf_index.
+	* configure: Regenerate.
+	* config.h.in [HAVE_BFD_ELF]: Likewise.
+	* libctf/ctf_open_bfd (ctf_bfdopen_ctfsect): Use it.
+	abfd is potentially unused now.
+
 2019-05-28  Nick Alcock  <nick.alcock@oracle.com>
 
 	* Makefile.am: New.
diff --git a/libctf/config.h.in b/libctf/config.h.in
index 8d87b3d08a..829201033e 100644
--- a/libctf/config.h.in
+++ b/libctf/config.h.in
@@ -1,5 +1,8 @@
 /* config.h.in.  Generated from configure.ac by autoheader.  */
 
+/* Whether libbfd was configured for an ELF target. */
+#undef HAVE_BFD_ELF
+
 /* Define to 1 if you have the <byteswap.h> header file. */
 #undef HAVE_BYTESWAP_H
 
diff --git a/libctf/configure b/libctf/configure
index 2213393673..1c0340125a 100755
--- a/libctf/configure
+++ b/libctf/configure
@@ -5974,6 +5974,114 @@ $as_echo "#define HAVE_MMAP 1" >>confdefs.h
 fi
 rm -f conftest.mmap conftest.txt
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5
+$as_echo_n "checking for library containing dlopen... " >&6; }
+if ${ac_cv_search_dlopen+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' dl; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_dlopen=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_dlopen+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_dlopen+:} false; then :
+
+else
+  ac_cv_search_dlopen=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5
+$as_echo "$ac_cv_search_dlopen" >&6; }
+ac_res=$ac_cv_search_dlopen
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+
+# Similar to GDB_AC_CHECK_BFD.
+OLD_CFLAGS=$CFLAGS
+OLD_LDFLAGS=$LDFLAGS
+OLD_LIBS=$LIBS
+# Put the old CFLAGS/LDFLAGS last, in case the user's (C|LD)FLAGS
+# points somewhere with bfd, with -I/foo/lib and -L/foo/lib.  We
+# always want our bfd.
+CFLAGS="-I${srcdir}/../include -I../bfd -I${srcdir}/../bfd $CFLAGS"
+ZLIBDIR=`echo $zlibdir | sed 's,\$(top_builddir)/,,g'`
+LDFLAGS="-L../bfd -L../libiberty $ZLIBDIR $LDFLAGS"
+intl=`echo $LIBINTL | sed 's,${top_builddir}/,,g'`
+LIBS="-lbfd -liberty -lz $intl $LIBS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ELF support in BFD" >&5
+$as_echo_n "checking for ELF support in BFD... " >&6; }
+if ${ac_cv_libctf_bfd_elf+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+	     #include "bfd.h"
+	     #include "elf-bfd.h"
+int
+main ()
+{
+(void) bfd_section_from_elf_index (NULL, 0);
+	     return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_libctf_bfd_elf=yes
+else
+  ac_cv_libctf_bfd_elf=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libctf_bfd_elf" >&5
+$as_echo "$ac_cv_libctf_bfd_elf" >&6; }
+CFLAGS=$OLD_CFLAGS
+LDFLAGS=$OLD_LDFLAGS
+LIBS=$OLD_LIBS
+
+if test $ac_cv_libctf_bfd_elf = yes; then
+
+$as_echo "#define HAVE_BFD_ELF 1" >>confdefs.h
+
+fi
+
 for ac_header in byteswap.h
 do :
   ac_fn_c_check_header_mongrel "$LINENO" "byteswap.h" "ac_cv_header_byteswap_h" "$ac_includes_default"
diff --git a/libctf/configure.ac b/libctf/configure.ac
index 2d0cf86bb7..2df10935c0 100644
--- a/libctf/configure.ac
+++ b/libctf/configure.ac
@@ -55,6 +55,37 @@ AM_MAINTAINER_MODE
 ACX_PROG_CC_WARNING_OPTS([-Wall], [ac_libctf_warn_cflags])
 
 AC_FUNC_MMAP
+AC_SEARCH_LIBS(dlopen, dl)
+
+# Similar to GDB_AC_CHECK_BFD.
+OLD_CFLAGS=$CFLAGS
+OLD_LDFLAGS=$LDFLAGS
+OLD_LIBS=$LIBS
+# Put the old CFLAGS/LDFLAGS last, in case the user's (C|LD)FLAGS
+# points somewhere with bfd, with -I/foo/lib and -L/foo/lib.  We
+# always want our bfd.
+CFLAGS="-I${srcdir}/../include -I../bfd -I${srcdir}/../bfd $CFLAGS"
+ZLIBDIR=`echo $zlibdir | sed 's,\$(top_builddir)/,,g'`
+LDFLAGS="-L../bfd -L../libiberty $ZLIBDIR $LDFLAGS"
+intl=`echo $LIBINTL | sed 's,${top_builddir}/,,g'`
+LIBS="-lbfd -liberty -lz $intl $LIBS"
+AC_CACHE_CHECK([for ELF support in BFD], ac_cv_libctf_bfd_elf,
+[AC_TRY_LINK([#include <stdlib.h>
+	     #include "bfd.h"
+	     #include "elf-bfd.h"],
+	    [(void) bfd_section_from_elf_index (NULL, 0);
+	     return 0;],
+	    [ac_cv_libctf_bfd_elf=yes],
+	    [ac_cv_libctf_bfd_elf=no])])
+CFLAGS=$OLD_CFLAGS
+LDFLAGS=$OLD_LDFLAGS
+LIBS=$OLD_LIBS
+
+if test $ac_cv_libctf_bfd_elf = yes; then
+  AC_DEFINE([HAVE_BFD_ELF], 1,
+	    [Whether libbfd was configured for an ELF target.])
+fi
+
 AC_CHECK_HEADERS(byteswap.h)
 AC_CHECK_FUNCS(pread)
 
diff --git a/libctf/ctf-open-bfd.c b/libctf/ctf-open-bfd.c
index d6d442ea42..5e34d12369 100644
--- a/libctf/ctf-open-bfd.c
+++ b/libctf/ctf-open-bfd.c
@@ -119,7 +119,8 @@ ctf_bfdopen (struct bfd *abfd, int *errp)
    later.  */
 
 ctf_archive_t *
-ctf_bfdopen_ctfsect (struct bfd *abfd, const ctf_sect_t *ctfsect, int *errp)
+ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_,
+		     const ctf_sect_t *ctfsect, int *errp)
 {
   struct ctf_archive *arc = NULL;
   ctf_archive_t *arci;
@@ -129,6 +130,7 @@ ctf_bfdopen_ctfsect (struct bfd *abfd, const ctf_sect_t *ctfsect, int *errp)
   const char *bfderrstr = NULL;
   int is_archive;
 
+#ifdef HAVE_BFD_ELF
   asection *sym_asect;
   ctf_sect_t symsect, strsect;
   /* TODO: handle SYMTAB_SHNDX.  */
@@ -178,6 +180,7 @@ ctf_bfdopen_ctfsect (struct bfd *abfd, const ctf_sect_t *ctfsect, int *errp)
 	  symsectp = &symsect;
 	}
     }
+#endif
 
   if (ctfsect->cts_size > sizeof (uint64_t) &&
       ((*(uint64_t *) ctfsect->cts_data) == CTFA_MAGIC))
@@ -203,9 +206,11 @@ ctf_bfdopen_ctfsect (struct bfd *abfd, const ctf_sect_t *ctfsect, int *errp)
   if (arci)
     return arci;
  err_free_sym:
+#ifdef HAVE_BFD_ELF
   free ((void *) symsect.cts_data);
 err_free_str:
   free ((void *) strsect.cts_data);
+#endif
 err: _libctf_unused_;
   if (bfderrstr)
     {

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v2 00/19] libctf, and CTF support for objdump and readelf
  2019-05-28 21:36       ` Nix
@ 2019-05-29  3:25         ` Alan Modra
  2019-05-29  9:14           ` Jose E. Marchesi
  0 siblings, 1 reply; 31+ messages in thread
From: Alan Modra @ 2019-05-29  3:25 UTC (permalink / raw)
  To: Nix; +Cc: Christophe Lyon, Jose E. Marchesi, Nick Clifton, binutils

On Tue, May 28, 2019 at 10:36:17PM +0100, Nix wrote:
> On 28 May 2019, Christophe Lyon stated:
> > One of the patches in the series broke the build for --target arm-pe:
> > ../libctf/libctf.a(ctf-open-bfd.o): In function `ctf_bfdopen_ctfsect':
> > /home/tcwg-buildslave/workspace/tcwg-binutils/bfd/--enable-64-bit-bfd=no/label/tcwg-x86_64-cam/target/arm-pe/build-arm-pe/libctf/../../libctf/ctf-open-bfd.c:136:
> > undefined reference to `bfd_section_from_elf_index'
> > /home/tcwg-buildslave/workspace/tcwg-binutils/bfd/--enable-64-bit-bfd=no/label/tcwg-x86_64-cam/target/arm-pe/build-arm-pe/libctf/../../libctf/ctf-open-bfd.c:145:
> > undefined reference to `bfd_section_from_elf_index'
> >
> > Can you check & fix?
> 
> Very sorry about that. My non-ELF platform of choice was mingw, which I
> now see pulls in the ELF bfd stuff! Ironically I had all the necessary
> ifdefs in place for the non-ELF builds but was intentionally trimming
> them out of the copy synced to binutils...
> 
> I am testing the fix below (on lots more targets, this time, so it might
> be a few hours). I hope the build system fiddling is right. It was... a
> bit counterintuitive, although all the changes made sense in hindsight.

It looks OK to me and fixes build failures on these targets that I test:
alpha-dec-vms
arm-pe
arm-wince-pe
hppa-hp-hpux10
i386-darwin
mcore-pe
ns32k-netbsd
ns32k-pc532-mach
pdp11-dec-aout
powerpc-aix5.1
powerpc-aix5.2
powerpcle-cygwin
rs6000-aix4.3.3
rs6000-aix5.1
rs6000-aix5.2
sh-pe
tic30-unknown-aout
tic30-unknown-coff
tic4x-coff
tic54x-coff
z80-coff
z8k-coff

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v2 00/19] libctf, and CTF support for objdump and readelf
  2019-05-29  3:25         ` Alan Modra
@ 2019-05-29  9:14           ` Jose E. Marchesi
  0 siblings, 0 replies; 31+ messages in thread
From: Jose E. Marchesi @ 2019-05-29  9:14 UTC (permalink / raw)
  To: Alan Modra; +Cc: Nix, Christophe Lyon, Nick Clifton, binutils


    > On 28 May 2019, Christophe Lyon stated:
    > > One of the patches in the series broke the build for --target arm-pe:
    > > ../libctf/libctf.a(ctf-open-bfd.o): In function `ctf_bfdopen_ctfsect':
    > > /home/tcwg-buildslave/workspace/tcwg-binutils/bfd/--enable-64-bit-bfd=no/label/tcwg-x86_64-cam/target/arm-pe/build-arm-pe/libctf/../../libctf/ctf-open-bfd.c:136:
    > > undefined reference to `bfd_section_from_elf_index'
    > > /home/tcwg-buildslave/workspace/tcwg-binutils/bfd/--enable-64-bit-bfd=no/label/tcwg-x86_64-cam/target/arm-pe/build-arm-pe/libctf/../../libctf/ctf-open-bfd.c:145:
    > > undefined reference to `bfd_section_from_elf_index'
    > >
    > > Can you check & fix?
    > 
    > Very sorry about that. My non-ELF platform of choice was mingw, which I
    > now see pulls in the ELF bfd stuff! Ironically I had all the necessary
    > ifdefs in place for the non-ELF builds but was intentionally trimming
    > them out of the copy synced to binutils...
    > 
    > I am testing the fix below (on lots more targets, this time, so it might
    > be a few hours). I hope the build system fiddling is right. It was... a
    > bit counterintuitive, although all the changes made sense in hindsight.
    
    It looks OK to me and fixes build failures on these targets that I
    test:
    alpha-dec-vms
    arm-pe
    arm-wince-pe
    hppa-hp-hpux10
    i386-darwin
    mcore-pe
    ns32k-netbsd
    ns32k-pc532-mach
    pdp11-dec-aout
    powerpc-aix5.1
    powerpc-aix5.2
    powerpcle-cygwin
    rs6000-aix4.3.3
    rs6000-aix5.1
    rs6000-aix5.2
    sh-pe
    tic30-unknown-aout
    tic30-unknown-coff
    tic4x-coff
    tic54x-coff
    z80-coff
    z8k-coff

I just pushed the fix in Nix's behalf.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v2 08/19] libctf: creation functions
  2019-05-17 22:10 ` [PATCH v2 08/19] libctf: creation functions Nick Alcock
@ 2019-05-29 14:09   ` Szabolcs Nagy
  2019-05-29 14:19     ` Nick Alcock
  0 siblings, 1 reply; 31+ messages in thread
From: Szabolcs Nagy @ 2019-05-29 14:09 UTC (permalink / raw)
  To: Nick Alcock, binutils; +Cc: nd

On 17/05/2019 23:09, Nick Alcock wrote:
> --- a/include/ctf-api.h
> +++ b/include/ctf-api.h
> @@ -27,6 +27,7 @@
>  #include <sys/param.h>
>  #include <sys/types.h>
>  #include <ctf.h>
> +#include <zlib.h>

is zlib guaranteed to be available everywhere where
ctf-api.h may be used?

in particular i see

In file included from /S/libctf/ctf-impl.h:25:0,
                 from /S/libctf/ctf-archive.c:20:
/S/libctf/../include/ctf-api.h:30:18: fatal error: zlib.h: No such file or directory
 #include <zlib.h>
                  ^
compilation terminated.
make[2]: *** [ctf-archive.o] Error 1

when the host has no zlib.h
(in that case the binutils internal zlib.h should be used,
ZLIBINC etc should be set up in the Makefile of libctf)


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v2 08/19] libctf: creation functions
  2019-05-29 14:09   ` Szabolcs Nagy
@ 2019-05-29 14:19     ` Nick Alcock
  0 siblings, 0 replies; 31+ messages in thread
From: Nick Alcock @ 2019-05-29 14:19 UTC (permalink / raw)
  To: Szabolcs Nagy; +Cc: binutils, nd

On 29 May 2019, Szabolcs Nagy spake thusly:

> On 17/05/2019 23:09, Nick Alcock wrote:
>> --- a/include/ctf-api.h
>> +++ b/include/ctf-api.h
>> @@ -27,6 +27,7 @@
>>  #include <sys/param.h>
>>  #include <sys/types.h>
>>  #include <ctf.h>
>> +#include <zlib.h>
>
> is zlib guaranteed to be available everywhere where
> ctf-api.h may be used?

I hoped to be using the internal implementation in that case.

> in particular i see
>
> In file included from /S/libctf/ctf-impl.h:25:0,
>                  from /S/libctf/ctf-archive.c:20:
> /S/libctf/../include/ctf-api.h:30:18: fatal error: zlib.h: No such file or directory
>  #include <zlib.h>
>                   ^
> compilation terminated.
> make[2]: *** [ctf-archive.o] Error 1
>
> when the host has no zlib.h
> (in that case the binutils internal zlib.h should be used,
> ZLIBINC etc should be set up in the Makefile of libctf)

Hm. I thought I'd done everything necessary for that (deps in
Makefile.tpl etc). Clearly I've missed something. I'll do what other
zlib users do...

-- 
NULL && (void)

^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2019-05-29 14:19 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-17 22:10 [PATCH v2 00/19] libctf, and CTF support for objdump and readelf Nick Alcock
2019-05-17 22:10 ` [PATCH v2 12/19] libctf: lookups by name and symbol Nick Alcock
2019-05-17 22:10 ` [PATCH v2 05/19] libctf: error handling Nick Alcock
2019-05-17 22:10 ` [PATCH v2 17/19] libctf: debug dumping Nick Alcock
2019-05-17 22:10 ` [PATCH v2 01/19] include: new header ctf.h: file format description Nick Alcock
2019-05-17 22:10 ` [PATCH v2 07/19] libctf: implementation definitions related to file creation Nick Alcock
2019-05-17 22:10 ` [PATCH v2 03/19] libctf: lowest-level memory allocation and debug-dumping wrappers Nick Alcock
2019-05-17 22:10 ` [PATCH v2 06/19] libctf: hashing Nick Alcock
2019-05-17 22:10 ` [PATCH v2 19/19] binutils: CTF support for objdump and readelf Nick Alcock
2019-05-17 22:10 ` [PATCH v2 15/19] libctf: mmappable archives Nick Alcock
2019-05-17 22:10 ` [PATCH v2 14/19] libctf: library version enforcement Nick Alcock
2019-05-17 22:10 ` [PATCH v2 08/19] libctf: creation functions Nick Alcock
2019-05-29 14:09   ` Szabolcs Nagy
2019-05-29 14:19     ` Nick Alcock
2019-05-17 22:10 ` [PATCH v2 04/19] libctf: low-level list manipulation and helper utilities Nick Alcock
2019-05-17 22:10 ` [PATCH v2 13/19] libctf: type copying Nick Alcock
2019-05-17 22:10 ` [PATCH v2 09/19] libctf: opening Nick Alcock
2019-05-17 22:10 ` [PATCH v2 10/19] libctf: ELF file opening via BFD Nick Alcock
2019-05-17 22:10 ` [PATCH v2 02/19] include: new header ctf-api.h Nick Alcock
2019-05-17 22:11 ` [PATCH v2 18/19] libctf: build system Nick Alcock
2019-05-17 22:12 ` [PATCH v2 16/19] libctf: labels Nick Alcock
2019-05-17 22:12 ` [PATCH v2 11/19] libctf: core type lookup Nick Alcock
2019-05-20 19:27 ` [PATCH v2 00/19] libctf, and CTF support for objdump and readelf Joseph Myers
2019-05-20 20:50   ` Nick Alcock
2019-05-28  8:33 ` Nick Clifton
2019-05-28  9:56   ` Nick Alcock
2019-05-28 16:39   ` Jose E. Marchesi
2019-05-28 19:16     ` Christophe Lyon
2019-05-28 21:36       ` Nix
2019-05-29  3:25         ` Alan Modra
2019-05-29  9:14           ` Jose E. Marchesi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).