[PATCH] Fix a number of build problems found on Solaris and NetBSD (was Re: Oh dear. I regret to inform you that commit 0e65dfbaf3a0299e4837216a103c28625d4b4f1d might be unfortunate)

Nick Alcock
2019-05-29T16:33:48Z

On 29 May 2019, Rainer Orth stated:

> Nix <nix@esperi.org.uk> writes:
>> I stripped almost all of these out, but it looks like one single one
>> survived. It is gone now.
>
> Thanks.

If you'd like to try the entirely unreviewed patch I'm trying out (works
for me on x86_64-pc-linux-gnu, i686-pc-linux-gnu, mingw, Solaris), here
it is:

commit ea9ad1fe21e0d42d554cb702b29cfc312cd5fd59
Author: Nick Alcock <nick.alcock@oracle.com>
Date: Wed May 29 15:07:06 2019 +0100

Fix a number of build problems found on Solaris and NetBSD

- Use of nonportable <endian.h>
- Use of qsort_r
- Use of zlib without appropriate magic to pull in the binutils zlib
- Use of off64_t without checking
- signedness problems due to long being too short a type on 32-bit
platforms: ctf_id_t is now 'unsigned long', and CTF_ERR must be
used only for functions that return ctf_id_t
- One lingering use of bzero() and of <sys/errno.h>

All fixed, using code from gnulib where possible.

include/
* ctf-api.h (HAVE_OFF64_T): Define off64_t if need be.
(ctf_id_t): This is now an unsigned type.
(CTF_ERR): Cast it to ctf_id_t. Note that it should only be used
for ctf_id_t-returning functions.
libctf/
* Makefile.am (ZLIB): New.
(ZLIBINC): Likewise.
(AM_CFLAGS): Use them.
(libctf_a_LIBADD): New, for LIBOBJS.
* configure.ac: Check for zlib, endian.h, off64_t, and qsort_r.
* ctf-endian.h: New, providing htole64 and le64toh.
* swap.h: Code style fixes.
(bswap_identity_64): New.
* qsort_r.c: New, from gnulib (with one added #include).
* ctf-decls.h: New, providing a conditional qsort_r declaration,
and unconditional definitions of MIN and MAX.
* ctf-impl.h: Use it. Do not use <sys/errno.h>.
(ctf_set_errno): Now returns unsigned long.
* ctf-util.c (ctf_set_errno): Adjust here too.
* ctf-archive.c: Use ctf-endian.h.
(ctf_arc_open_by_offset): Use memset, not bzero.
(ctf_arc_write): Drop debugging dependent on the size of off_t.
* ctf-create.c: Provide a definition of roundup if not defined.
(ctf_add_reftype): Do not check if type IDs are below zero.
(ctf_add_slice): Likewise.
(ctf_add_typedef): Likewise.
(ctf_add_member_offset): Cast error-returning ssize_t's to size_t
when known error-free. Drop CTF_ERR usage for functions returning
int.
(ctf_add_member_encoded): Drop CTF_ERR usage for functions returning
int.
(ctf_add_variable): Likewise.
(enumcmp): Likewise.
(enumadd): Likewise.
(membcmp): Likewise.
(ctf_add_type): Likewise. Cast error-returning ssize_t's to size_t
when known error-free.
* ctf-dump.c (ctf_is_slice): Drop CTF_ERR usage for functions
returning int: use CTF_ERR for functions returning ctf_type_id.
(ctf_dump_label): Likewise.
(ctf_dump_objts): Likewise.
* ctf-labels.c (ctf_label_topmost): Likewise.
(ctf_label_iter): Likewise.
(ctf_label_info): Likewise.
* ctf-lookup.c (ctf_func_args): Likewise.
* ctf-open.c (upgrade_types): Cast to size_t where appropriate.
(ctf_bufopen): Likewise. Use zlib types as needed.
* ctf-types.c (ctf_member_iter): Drop CTF_ERR usage for functions
returning int.
(ctf_enum_iter): Likewise.
(ctf_type_size): Likewise.
(ctf_type_align): Likewise. Cast to size_t where appropriate.
(ctf_type_kind_unsliced): Likewise.
(ctf_type_kind): Likewise.
(ctf_type_encoding): Likewise.
(ctf_member_info): Likewise.
(ctf_array_info): Likewise.
(ctf_enum_value): Likewise.
(ctf_type_rvisit): Likewise.
* Makefile.in: Regenerate.
* aclocal.m4: Likewise.
* config.h: Likewise.
* configure: Likewise.

diff --git a/include/ChangeLog b/include/ChangeLog
index 05083763b1..1ad53db690 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,10 @@
+2019-05-29 Nick Alcock <nick.alcock@oracle.com>
+
+ * ctf-api.h (HAVE_OFF64_T): Define off64_t if need be.
+ (ctf_id_t): This is now an unsigned type.
+ (CTF_ERR): Cast it to ctf_id_t. Note that it should only be used
+ for ctf_id_t-returning functions.
+
2019-05-28 Nick Alcock <nick.alcock@oracle.com>

* ctf-api.h (ctf_dump_decorate_f): New.
diff --git a/include/ctf-api.h b/include/ctf-api.h
index 822b3bf5a9..5d9274c55d 100644
--- a/include/ctf-api.h
+++ b/include/ctf-api.h
@@ -29,6 +29,10 @@
#include <ctf.h>
#include <zlib.h>

+#ifndef HAVE_OFF64_T
+#define off64_t off_t
+#endif
+
#ifdef __cplusplus
extern "C"
{
@@ -43,7 +47,7 @@ extern "C"

typedef struct ctf_file ctf_file_t;
typedef struct ctf_archive_internal ctf_archive_t;
-typedef long ctf_id_t;
+typedef unsigned long ctf_id_t;

/* This opaque definition allows libctf to accept BFD data structures without
importing all the BFD noise into users' namespaces. */
@@ -125,9 +129,10 @@ typedef struct ctf_snapshot_id

#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)
+/* Functions that return a ctf_id_t use the following value to indicate failure.
+ ctf_errno() can be used to obtain an error code. Functions that return
+ a straight integral -1 also use ctf_errno(). */
+#define CTF_ERR ((ctf_id_t) -1L)

#define ECTF_BASE 1000 /* Base value for libctf errnos. */

diff --git a/libctf/ChangeLog b/libctf/ChangeLog
index 879aeed38f..d4e760f576 100644
--- a/libctf/ChangeLog
+++ b/libctf/ChangeLog
@@ -1,3 +1,64 @@
+2019-05-29 Nick Alcock <nick.alcock@oracle.com>
+
+ * Makefile.am (ZLIB): New.
+ (ZLIBINC): Likewise.
+ (AM_CFLAGS): Use them.
+ (libctf_a_LIBADD): New, for LIBOBJS.
+ * configure.ac: Check for zlib, endian.h, off64_t, and qsort_r.
+ * ctf-endian.h: New, providing htole64 and le64toh.
+ * swap.h: Code style fixes.
+ (bswap_identity_64): New.
+ * qsort_r.c: New, from gnulib (with one added #include).
+ * ctf-decls.h: New, providing a conditional qsort_r declaration,
+ and unconditional definitions of MIN and MAX.
+ * ctf-impl.h: Use it. Do not use <sys/errno.h>.
+ (ctf_set_errno): Now returns unsigned long.
+ * ctf-util.c (ctf_set_errno): Adjust here too.
+ * ctf-archive.c: Use ctf-endian.h.
+ (ctf_arc_open_by_offset): Use memset, not bzero.
+ (ctf_arc_write): Drop debugging dependent on the size of off_t.
+ * ctf-create.c: Provide a definition of roundup if not defined.
+ (ctf_add_reftype): Do not check if type IDs are below zero.
+ (ctf_add_slice): Likewise.
+ (ctf_add_typedef): Likewise.
+ (ctf_add_member_offset): Cast error-returning ssize_t's to size_t
+ when known error-free. Drop CTF_ERR usage for functions returning
+ int.
+ (ctf_add_member_encoded): Drop CTF_ERR usage for functions returning
+ int.
+ (ctf_add_variable): Likewise.
+ (enumcmp): Likewise.
+ (enumadd): Likewise.
+ (membcmp): Likewise.
+ (ctf_add_type): Likewise. Cast error-returning ssize_t's to size_t
+ when known error-free.
+ * ctf-dump.c (ctf_is_slice): Drop CTF_ERR usage for functions
+ returning int: use CTF_ERR for functions returning ctf_type_id.
+ (ctf_dump_label): Likewise.
+ (ctf_dump_objts): Likewise.
+ * ctf-labels.c (ctf_label_topmost): Likewise.
+ (ctf_label_iter): Likewise.
+ (ctf_label_info): Likewise.
+ * ctf-lookup.c (ctf_func_args): Likewise.
+ * ctf-open.c (upgrade_types): Cast to size_t where appropriate.
+ (ctf_bufopen): Likewise. Use zlib types as needed.
+ * ctf-types.c (ctf_member_iter): Drop CTF_ERR usage for functions
+ returning int.
+ (ctf_enum_iter): Likewise.
+ (ctf_type_size): Likewise.
+ (ctf_type_align): Likewise. Cast to size_t where appropriate.
+ (ctf_type_kind_unsliced): Likewise.
+ (ctf_type_kind): Likewise.
+ (ctf_type_encoding): Likewise.
+ (ctf_member_info): Likewise.
+ (ctf_array_info): Likewise.
+ (ctf_enum_value): Likewise.
+ (ctf_type_rvisit): Likewise.
+ * Makefile.in: Regenerate.
+ * aclocal.m4: Likewise.
+ * config.h: Likewise.
+ * configure: Likewise.
+
2019-05-28 Nick Alcock <nick.alcock@oracle.com>

* configure.in: Check for bfd_section_from_elf_index.
diff --git a/libctf/Makefile.am b/libctf/Makefile.am
index 5fe2c95901..49c9f5280a 100644
--- a/libctf/Makefile.am
+++ b/libctf/Makefile.am
@@ -21,11 +21,18 @@ ACLOCAL_AMFLAGS = -I .. -I ../config

AUTOMAKE_OPTIONS = foreign no-texinfo.tex

+# This is where we get zlib from. zlibdir is -L../zlib and zlibinc is
+# -I../zlib, unless we were configured with --with-system-zlib, in which
+# case both are empty.
+ZLIB = @zlibdir@ -lz
+ZLIBINC = @zlibinc@
+
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@
+AM_CFLAGS = -std=gnu99 @ac_libctf_warn_cflags@ @warn@ @c_warn@ @WARN_PEDANTIC@ @WERROR@ $(ZLIBINC)

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
+libctf_a_LIBADD = $(LIBOBJS)
diff --git a/libctf/Makefile.in b/libctf/Makefile.in
index b0afa5b80d..c2cada6616 100644
--- a/libctf/Makefile.in
+++ b/libctf/Makefile.in
@@ -109,7 +109,8 @@ 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
+ $(top_srcdir)/../config/warnings.m4 \
+ $(top_srcdir)/../config/zlib.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
@@ -127,7 +128,7 @@ 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 =
+libctf_a_DEPENDENCIES = $(LIBOBJS)
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) \
@@ -194,7 +195,8 @@ 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
+ $(top_srcdir)/../missing $(top_srcdir)/../mkinstalldirs \
+ ChangeLog qsort_r.c
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
@@ -308,15 +310,24 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
warn = @warn@
+zlibdir = @zlibdir@
+zlibinc = @zlibinc@
ACLOCAL_AMFLAGS = -I .. -I ../config
AUTOMAKE_OPTIONS = foreign no-texinfo.tex
+
+# This is where we get zlib from. zlibdir is -L../zlib and zlibinc is
+# -I../zlib, unless we were configured with --with-system-zlib, in which
+# case both are empty.
+ZLIB = @zlibdir@ -lz
+ZLIBINC = @zlibinc@
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@
+AM_CFLAGS = -std=gnu99 @ac_libctf_warn_cflags@ @warn@ @c_warn@ @WARN_PEDANTIC@ @WERROR@ $(ZLIBINC)
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

+libctf_a_LIBADD = $(LIBOBJS)
all: config.h
$(MAKE) $(AM_MAKEFLAGS) all-am

@@ -385,6 +396,7 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c

+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/qsort_r.Po@am__quote@
@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@
@@ -675,7 +687,7 @@ clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am

distclean: distclean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
- -rm -rf ./$(DEPDIR)
+ -rm -rf $(DEPDIR) ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-hdr distclean-tags
@@ -723,7 +735,7 @@ installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf $(top_srcdir)/autom4te.cache
- -rm -rf ./$(DEPDIR)
+ -rm -rf $(DEPDIR) ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic

diff --git a/libctf/aclocal.m4 b/libctf/aclocal.m4
index d792e62dfb..074f03638f 100644
--- a/libctf/aclocal.m4
+++ b/libctf/aclocal.m4
@@ -1231,3 +1231,4 @@ m4_include([../config/depstand.m4])
m4_include([../config/lead-dot.m4])
m4_include([../config/override.m4])
m4_include([../config/warnings.m4])
+m4_include([../config/zlib.m4])
diff --git a/libctf/config.h.in b/libctf/config.h.in
index 829201033e..afdfeecd3a 100644
--- a/libctf/config.h.in
+++ b/libctf/config.h.in
@@ -1,11 +1,21 @@
/* config.h.in. Generated from configure.ac by autoheader. */

+/* Define if building universal (internal helper macro) */
+#undef AC_APPLE_UNIVERSAL_BUILD
+
/* 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

+/* Define to 1 if you have the declaration of `qsort_r', and to 0 if you
+ don't. */
+#undef HAVE_DECL_QSORT_R
+
+/* Define to 1 if you have the <endian.h> header file. */
+#undef HAVE_ENDIAN_H
+
/* Define to 1 if you have the `getpagesize' function. */
#undef HAVE_GETPAGESIZE

@@ -18,6 +28,9 @@
/* Define to 1 if you have a working `mmap' system call. */
#undef HAVE_MMAP

+/* Define to 1 if the system has the type `off64_t'. */
+#undef HAVE_OFF64_T
+
/* Define to 1 if you have the `pread' function. */
#undef HAVE_PREAD

@@ -94,6 +107,18 @@
/* Version number of package */
#undef VERSION

+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+ significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+# define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+# undef WORDS_BIGENDIAN
+# endif
+#endif
+
/* Enable large inode numbers on Mac OS X 10.5. */
#ifndef _DARWIN_USE_64_BIT_INODE
# define _DARWIN_USE_64_BIT_INODE 1
diff --git a/libctf/configure b/libctf/configure
index 1c0340125a..4a8ca2708f 100755
--- a/libctf/configure
+++ b/libctf/configure
@@ -624,6 +624,8 @@ ac_subst_vars='am__EXEEXT_FALSE
am__EXEEXT_TRUE
LTLIBOBJS
LIBOBJS
+zlibinc
+zlibdir
ac_libctf_warn_cflags
MAINT
MAINTAINER_MODE_FALSE
@@ -728,6 +730,7 @@ enable_silent_rules
enable_largefile
enable_werror_always
enable_maintainer_mode
+with_system_zlib
'
ac_precious_vars='build_alias
host_alias
@@ -1364,6 +1367,11 @@ Optional Features:
enable make rules and dependencies not useful (and
sometimes confusing) to the casual installer

+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-system-zlib use installed libz
+
Some influential environment variables:
CC C compiler command
CFLAGS C compiler flags
@@ -1801,6 +1809,106 @@ $as_echo "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno

} # ac_fn_c_check_func
+
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+ 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
+ eval "$3=no"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ eval "$3=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
+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_type
+
+# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
+# ---------------------------------------------
+# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
+# accordingly.
+ac_fn_c_check_decl ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ as_decl_name=`echo $2|sed 's/ *(.*//'`
+ as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+#ifndef $as_decl_name
+#ifdef __cplusplus
+ (void) $as_decl_use;
+#else
+ (void) $as_decl_name;
+#endif
+#endif
+
+ ;
+ return 0;
+}
+_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_decl
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
@@ -6031,6 +6139,23 @@ if test "$ac_res" != no; then :
fi

+ # Use the system's zlib library.
+ zlibdir="-L\$(top_builddir)/../zlib"
+ zlibinc="-I\$(top_srcdir)/../zlib"
+
+# Check whether --with-system-zlib was given.
+if test "${with_system_zlib+set}" = set; then :
+ withval=$with_system_zlib; if test x$with_system_zlib = xyes ; then
+ zlibdir=
+ zlibinc=
+ fi
+
+fi
+
+
+
+
+
# Similar to GDB_AC_CHECK_BFD.
OLD_CFLAGS=$CFLAGS
OLD_LDFLAGS=$LDFLAGS
@@ -6082,18 +6207,253 @@ $as_echo "#define HAVE_BFD_ELF 1" >>confdefs.h

fi

-for ac_header in byteswap.h
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
+$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
+if ${ac_cv_c_bigendian+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_c_bigendian=unknown
+ # See if we're dealing with a universal compiler.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifndef __APPLE_CC__
+ not a universal capable compiler
+ #endif
+ typedef int dummy;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ # Check for potential -arch flags. It is not universal unless
+ # there are at least two -arch flags with different values.
+ ac_arch=
+ ac_prev=
+ for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do
+ if test -n "$ac_prev"; then
+ case $ac_word in
+ i?86 | x86_64 | ppc | ppc64)
+ if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then
+ ac_arch=$ac_word
+ else
+ ac_cv_c_bigendian=universal
+ break
+ fi
+ ;;
+ esac
+ ac_prev=
+ elif test "x$ac_word" = "x-arch"; then
+ ac_prev=arch
+ fi
+ done
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ if test $ac_cv_c_bigendian = unknown; then
+ # See if sys/param.h defines the BYTE_ORDER macro.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <sys/param.h>
+
+int
+main ()
+{
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
+ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
+ && LITTLE_ENDIAN)
+ bogus endian macros
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ # It does; now see whether it defined to BIG_ENDIAN or not.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_bigendian=yes
+else
+ ac_cv_c_bigendian=no
+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
+ if test $ac_cv_c_bigendian = unknown; then
+ # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+
+int
+main ()
+{
+#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
+ bogus endian macros
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ # It does; now see whether it defined to _BIG_ENDIAN or not.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+
+int
+main ()
+{
+#ifndef _BIG_ENDIAN
+ not big endian
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_bigendian=yes
+else
+ ac_cv_c_bigendian=no
+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
+ if test $ac_cv_c_bigendian = unknown; then
+ # Compile a test program.
+ if test "$cross_compiling" = yes; then :
+ # Try to guess by grepping values from an object file.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+short int ascii_mm[] =
+ { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+ short int ascii_ii[] =
+ { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+ int use_ascii (int i) {
+ return ascii_mm[i] + ascii_ii[i];
+ }
+ short int ebcdic_ii[] =
+ { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+ short int ebcdic_mm[] =
+ { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+ int use_ebcdic (int i) {
+ return ebcdic_mm[i] + ebcdic_ii[i];
+ }
+ extern int foo;
+
+int
+main ()
+{
+return use_ascii (foo) == use_ebcdic (foo);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
+ ac_cv_c_bigendian=yes
+ fi
+ if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+ if test "$ac_cv_c_bigendian" = unknown; then
+ ac_cv_c_bigendian=no
+ else
+ # finding both strings is unlikely to happen, but who knows?
+ ac_cv_c_bigendian=unknown
+ fi
+ fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+
+ /* Are we little or big endian? From Harbison&Steele. */
+ union
+ {
+ long int l;
+ char c[sizeof (long int)];
+ } u;
+ u.l = 1;
+ return u.c[sizeof (long int) - 1] == 1;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_c_bigendian=no
+else
+ ac_cv_c_bigendian=yes
+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_c_bigendian" >&5
+$as_echo "$ac_cv_c_bigendian" >&6; }
+ case $ac_cv_c_bigendian in #(
+ yes)
+ $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h
+;; #(
+ no)
+ ;; #(
+ universal)
+
+$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
+
+ ;; #(
+ *)
+ as_fn_error $? "unknown endianness
+ presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;;
+ esac
+
+for ac_header in byteswap.h endian.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 :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
-#define HAVE_BYTESWAP_H 1
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF

fi

done

+ac_fn_c_check_type "$LINENO" "off64_t" "ac_cv_type_off64_t" "$ac_includes_default"
+if test "x$ac_cv_type_off64_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_OFF64_T 1
+_ACEOF
+
+
+fi
+
for ac_func in pread
do :
ac_fn_c_check_func "$LINENO" "pread" "ac_cv_func_pread"
@@ -6105,6 +6465,23 @@ _ACEOF
fi
done

+ac_fn_c_check_decl "$LINENO" "qsort_r" "ac_cv_have_decl_qsort_r" "$ac_includes_default"
+if test "x$ac_cv_have_decl_qsort_r" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_QSORT_R $ac_have_decl
+_ACEOF
+
+case " $LIBOBJS " in
+ *" qsort_r.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS qsort_r.$ac_objext"
+ ;;
+esac
+

ac_config_files="$ac_config_files Makefile"

@@ -6248,6 +6625,7 @@ if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
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
diff --git a/libctf/configure.ac b/libctf/configure.ac
index 2df10935c0..6a2eb500ee 100644
--- a/libctf/configure.ac
+++ b/libctf/configure.ac
@@ -56,6 +56,7 @@ ACX_PROG_CC_WARNING_OPTS([-Wall], [ac_libctf_warn_cflags])

AC_FUNC_MMAP
AC_SEARCH_LIBS(dlopen, dl)
+AM_ZLIB

# Similar to GDB_AC_CHECK_BFD.
OLD_CFLAGS=$CFLAGS
@@ -86,8 +87,12 @@ if test $ac_cv_libctf_bfd_elf = yes; then
[Whether libbfd was configured for an ELF target.])
fi

-AC_CHECK_HEADERS(byteswap.h)
+AC_C_BIGENDIAN
+AC_CHECK_HEADERS(byteswap.h endian.h)
+AC_CHECK_TYPES(off64_t)
AC_CHECK_FUNCS(pread)
+AC_CHECK_DECLS([qsort_r])
+AC_LIBOBJ([qsort_r])

AC_CONFIG_FILES(Makefile)
AC_CONFIG_HEADERS(config.h)
diff --git a/libctf/ctf-archive.c b/libctf/ctf-archive.c
index ab658fd351..f68bc13e60 100644
--- a/libctf/ctf-archive.c
+++ b/libctf/ctf-archive.c
@@ -21,7 +21,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <elf.h>
-#include <endian.h>
+#include "ctf-endian.h"
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
@@ -150,7 +150,6 @@ ctf_arc_write (const char *file, ctf_file_t ** ctf_files, size_t ctf_file_cnt,
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 "
@@ -512,7 +511,7 @@ ctf_arc_open_by_offset (const struct ctf_archive *arc,

ctf_dprintf ("ctf_arc_open_by_offset(%zi): opening\n", offset);

- bzero (&ctfsect, sizeof (ctf_sect_t));
+ memset (&ctfsect, 0, sizeof (ctf_sect_t));

offset += le64toh (arc->ctfa_ctfs);

diff --git a/libctf/ctf-create.c b/libctf/ctf-create.c
index 5409ca4bb4..35d525927e 100644
--- a/libctf/ctf-create.c
+++ b/libctf/ctf-create.c
@@ -23,6 +23,10 @@
#include <string.h>
#include <zlib.h>

+#ifndef roundup
+#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
+#endif
+
/* 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
@@ -812,7 +816,7 @@ ctf_add_reftype (ctf_file_t *fp, uint32_t flag, ctf_id_t ref, uint32_t kind)
ctf_id_t type;
ctf_file_t *tmp = fp;

- if (ref == CTF_ERR || ref < 0 || ref > CTF_MAX_TYPE)
+ if (ref == CTF_ERR || ref > CTF_MAX_TYPE)
return (ctf_set_errno (fp, EINVAL));

if (ctf_lookup_by_id (&tmp, ref) == NULL)
@@ -843,7 +847,7 @@ ctf_add_slice (ctf_file_t *fp, uint32_t flag, ctf_id_t ref,
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)
+ if (ref == CTF_ERR || ref > CTF_MAX_TYPE)
return (ctf_set_errno (fp, EINVAL));

if ((tp = ctf_lookup_by_id (&tmp, ref)) == NULL)
@@ -1175,7 +1179,7 @@ ctf_add_typedef (ctf_file_t *fp, uint32_t flag, const char *name,
ctf_id_t type;
ctf_file_t *tmp = fp;

- if (ref == CTF_ERR || ref < 0 || ref > CTF_MAX_TYPE)
+ if (ref == CTF_ERR || ref > CTF_MAX_TYPE)
return (ctf_set_errno (fp, EINVAL));

if (ctf_lookup_by_id (&tmp, ref) == NULL)
@@ -1304,9 +1308,9 @@ ctf_add_member_offset (ctf_file_t *fp, ctf_id_t souid, const char *name,
}
}

- 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 ((msize = ctf_type_size (fp, type)) < 0 ||
+ (malign = ctf_type_align (fp, type)) < 0)
+ return -1; /* errno is set for us. */

if ((dmd = ctf_alloc (sizeof (ctf_dmdef_t))) == NULL)
return (ctf_set_errno (fp, EAGAIN));
@@ -1334,9 +1338,9 @@ ctf_add_member_offset (ctf_file_t *fp, ctf_id_t souid, const char *name,
ctf_encoding_t linfo;
ssize_t lsize;

- if (ctf_type_encoding (fp, ltype, &linfo) != CTF_ERR)
+ if (ctf_type_encoding (fp, ltype, &linfo) == 0)
off += linfo.cte_bits;
- else if ((lsize = ctf_type_size (fp, ltype)) != CTF_ERR)
+ else if ((lsize = ctf_type_size (fp, ltype)) > 0)
off += lsize * NBBY;

/* Round up the offset of the end of the last member to
@@ -1359,7 +1363,7 @@ ctf_add_member_offset (ctf_file_t *fp, ctf_id_t souid, const char *name,

dmd->dmd_offset = bit_offset;
ssize = ctf_get_ctt_size (fp, &dtd->dtd_data, NULL, NULL);
- ssize = MAX (ssize, (bit_offset / NBBY) + msize);
+ ssize = MAX (ssize, ((signed) bit_offset / NBBY) + msize);
}
}
else
@@ -1369,7 +1373,7 @@ ctf_add_member_offset (ctf_file_t *fp, ctf_id_t souid, const char *name,
ssize = MAX (ssize, msize);
}

- if (ssize > CTF_MAX_SIZE)
+ if ((size_t) ssize > CTF_MAX_SIZE)
{
dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (ssize);
@@ -1401,7 +1405,7 @@ ctf_add_member_encoded (ctf_file_t *fp, ctf_id_t souid, const char *name,
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 -1; /* errno is set for us. */

return ctf_add_member_offset (fp, souid, name, type, bit_offset);
}
@@ -1426,7 +1430,7 @@ ctf_add_variable (ctf_file_t *fp, const char *name, ctf_id_t ref)
return (ctf_set_errno (fp, ECTF_DUPLICATE));

if (ctf_lookup_by_id (&tmp, ref) == NULL)
- return CTF_ERR; /* errno is set for us. */
+ return -1; /* errno is set for us. */

if ((dvd = ctf_alloc (sizeof (ctf_dvdef_t))) == NULL)
return (ctf_set_errno (fp, EAGAIN));
@@ -1452,7 +1456,7 @@ 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)
+ if (ctf_enum_value (ctb->ctb_file, ctb->ctb_type, name, &bvalue) < 0)
{
ctf_dprintf ("Conflict due to member %s iteration error.\n", name);
return 1;
@@ -1472,7 +1476,7 @@ 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);
+ name, value) < 0);
}

static int
@@ -1482,7 +1486,7 @@ membcmp (const char *name, ctf_id_t type _libctf_unused_, unsigned long offset,
ctf_bundle_t *ctb = arg;
ctf_membinfo_t ctm;

- if (ctf_member_info (ctb->ctb_file, ctb->ctb_type, name, &ctm) == CTF_ERR)
+ if (ctf_member_info (ctb->ctb_file, ctb->ctb_type, name, &ctm) < 0)
{
ctf_dprintf ("Conflict due to member %s iteration error.\n", name);
return 1;
@@ -1550,7 +1554,6 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)

ctf_dtdef_t *dtd;
ctf_funcinfo_t ctc;
- ssize_t size;

ctf_hash_t *hp;

@@ -1756,7 +1759,7 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
break;

case CTF_K_ARRAY:
- if (ctf_array_info (src_fp, src_type, &src_ar) == CTF_ERR)
+ if (ctf_array_info (src_fp, src_type, &src_ar) != 0)
return (ctf_set_errno (dst_fp, ctf_errno (src_fp)));

src_ar.ctr_contents =
@@ -1803,6 +1806,8 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
{
ctf_dmdef_t *dmd;
int errs = 0;
+ size_t size;
+ ssize_t ssize;

/* Technically to match a struct or union we need to check both
ways (src members vs. dst, dst members vs. src) but we make
@@ -1818,7 +1823,7 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t 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",
+ "union size differs, old %zi, new %zi\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));
@@ -1848,7 +1853,11 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
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)
+ if ((ssize = ctf_type_size (src_fp, src_type)) < 0)
+ return CTF_ERR; /* errno is set for us. */
+
+ size = (size_t) ssize;
+ if (size > CTF_MAX_SIZE)
{
dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (size);
diff --git a/libctf/ctf-decls.h b/libctf/ctf-decls.h
new file mode 100644
index 0000000000..5e9ede4809
--- /dev/null
+++ b/libctf/ctf-decls.h
@@ -0,0 +1,37 @@
+/* Declarations for missing 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/>. */
+
+#ifndef _CTF_DECLS_H
+#define _CTF_DECLS_H
+
+#include "config.h"
+
+#if !HAVE_DECL_QSORT_R
+#include <stddef.h>
+void qsort_r (void *base, size_t nmemb, size_t size,
+ int (*compar)(const void *, const void *, void *),
+ void *arg);
+#endif /* !HAVE_DECL_QSORT_R */
+
+#undef MAX
+#undef MIN
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+#endif /* _CTF_DECLS_H */
diff --git a/libctf/ctf-dump.c b/libctf/ctf-dump.c
index 28f31e4872..c2ed791eea 100644
--- a/libctf/ctf-dump.c
+++ b/libctf/ctf-dump.c
@@ -88,7 +88,7 @@ ctf_is_slice (ctf_file_t *fp, ctf_id_t id, ctf_encoding_t *enc)
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);
+ && ctf_type_encoding (fp, id, enc) == 0);
}

/* Return a dump for a single type, without member info: but do show the
@@ -168,7 +168,7 @@ ctf_dump_label (const char *name, const ctf_lblinfo_t *info,
if ((typestr = ctf_dump_format_type (state->cds_fp, info->ctb_type)) == NULL)
{
free (str);
- return CTF_ERR; /* errno is set for us. */
+ return -1; /* errno is set for us. */
}

str = ctf_str_append (str, typestr);
@@ -194,14 +194,14 @@ ctf_dump_objts (ctf_file_t *fp, ctf_dump_state_t *state)
const char *sym_name;
ctf_id_t type;

- if ((type = ctf_lookup_by_symbol (state->cds_fp, i)) < 0)
+ if ((type = ctf_lookup_by_symbol (state->cds_fp, i)) == CTF_ERR)
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;
+ return -1;
case ECTF_NOTDATA:
case ECTF_NOTYPEDAT:
continue;
@@ -224,7 +224,7 @@ ctf_dump_objts (ctf_file_t *fp, ctf_dump_state_t *state)
if ((typestr = ctf_dump_format_type (state->cds_fp, type)) == NULL)
{
free (str);
- return CTF_ERR; /* errno is set for us. */
+ return -1; /* errno is set for us. */
}

str = ctf_str_append (str, typestr);
@@ -253,14 +253,14 @@ ctf_dump_funcs (ctf_file_t *fp, ctf_dump_state_t *state)
size_t j;
ctf_id_t *args;

- if ((type = ctf_func_info (state->cds_fp, i, &fi)) < 0)
+ if ((type = ctf_func_info (state->cds_fp, i, &fi)) == CTF_ERR)
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;
+ return -1;
case ECTF_NOTDATA:
case ECTF_NOTYPEDAT:
continue;
@@ -321,7 +321,7 @@ ctf_dump_funcs (ctf_file_t *fp, ctf_dump_state_t *state)
err:
free (args);
free (str);
- return CTF_ERR; /* errno is set for us. */
+ return -1; /* errno is set for us. */
}
return 0;
}
@@ -340,7 +340,7 @@ ctf_dump_var (const char *name, ctf_id_t type, void *arg)
if ((typestr = ctf_dump_format_type (state->cds_fp, type)) == NULL)
{
free (str);
- return CTF_ERR; /* errno is set for us. */
+ return -1; /* errno is set for us. */
}

str = ctf_str_append (str, typestr);
@@ -426,7 +426,7 @@ ctf_dump_type (ctf_id_t id, void *arg)

err:
free (str);
- return CTF_ERR; /* errno is set for us. */
+ return -1; /* errno is set for us. */
}

/* Dump the string table into the cds_items. */
diff --git a/libctf/ctf-endian.h b/libctf/ctf-endian.h
new file mode 100644
index 0000000000..ec177d1bdd
--- /dev/null
+++ b/libctf/ctf-endian.h
@@ -0,0 +1,37 @@
+/* Interface to endianness-neutrality 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/>. */
+
+#ifndef _CTF_ENDIAN_H
+#define _CTF_ENDIAN_H
+
+#include "config.h"
+#include <stdint.h>
+#include "swap.h"
+
+#ifndef HAVE_ENDIAN_H
+#ifndef WORDS_BIGENDIAN
+# define htole64(x) bswap_identity_64 ((x))
+# define le64toh(x) bswap_identity_64 ((x))
+#else
+# define htole64(x) bswap_64 ((x))
+# define le64toh(x) bswap_64 ((x))
+#endif /* WORDS_BIGENDIAN */
+#endif /* !defined(HAVE_ENDIAN_H) */
+
+#endif /* !defined(_CTF_ENDIAN_H) */
diff --git a/libctf/ctf-impl.h b/libctf/ctf-impl.h
index 363b62de7d..fa9c574941 100644
--- a/libctf/ctf-impl.h
+++ b/libctf/ctf-impl.h
@@ -21,7 +21,8 @@
#define _CTF_IMPL_H

#include "config.h"
-#include <sys/errno.h>
+#include <errno.h>
+#include "ctf-decls.h"
#include <ctf-api.h>
#include <sys/types.h>
#include <stdlib.h>
@@ -339,7 +340,7 @@ extern struct ctf_archive *ctf_arc_open_internal (const char *, int *);
extern struct ctf_archive *ctf_arc_bufopen (const void *, size_t, int *);
extern void ctf_arc_close_internal (struct ctf_archive *);
extern void *ctf_set_open_errno (int *, int);
-extern long ctf_set_errno (ctf_file_t *, int);
+extern unsigned long ctf_set_errno (ctf_file_t *, int);

_libctf_malloc_
extern void *ctf_data_alloc (size_t);
diff --git a/libctf/ctf-labels.c b/libctf/ctf-labels.c
index 9b9fffea4e..1755b9720a 100644
--- a/libctf/ctf-labels.c
+++ b/libctf/ctf-labels.c
@@ -43,7 +43,7 @@ ctf_label_topmost (ctf_file_t *fp)
const char *s;
uint32_t num_labels = 0;

- if (extract_label_info (fp, &ctlp, &num_labels) == CTF_ERR)
+ if (extract_label_info (fp, &ctlp, &num_labels) < 0)
return NULL; /* errno is set for us. */

if (num_labels == 0)
@@ -70,8 +70,8 @@ ctf_label_iter (ctf_file_t *fp, ctf_label_f *func, void *arg)
const char *lname;
int rc;

- if (extract_label_info (fp, &ctlp, &num_labels) == CTF_ERR)
- return CTF_ERR; /* errno is set for us. */
+ if (extract_label_info (fp, &ctlp, &num_labels) < 0)
+ return -1; /* errno is set for us. */

if (num_labels == 0)
return (ctf_set_errno (fp, ECTF_NOLABELDATA));
@@ -128,7 +128,7 @@ ctf_label_info (ctf_file_t *fp, const char *lname, ctf_lblinfo_t *linfo)
cb_arg.lca_name = lname;
cb_arg.lca_info = linfo;

- if ((rc = ctf_label_iter (fp, label_info_cb, &cb_arg)) == CTF_ERR)
+ if ((rc = ctf_label_iter (fp, label_info_cb, &cb_arg)) < 0)
return rc;

if (rc != 1)
diff --git a/libctf/ctf-lookup.c b/libctf/ctf-lookup.c
index 7ea46a7295..ab12715f4b 100644
--- a/libctf/ctf-lookup.c
+++ b/libctf/ctf-lookup.c
@@ -412,8 +412,8 @@ ctf_func_args (ctf_file_t * fp, unsigned long symidx, uint32_t argc,
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. */
+ if (ctf_func_info (fp, symidx, &f) < 0)
+ return -1; /* 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. */
diff --git a/libctf/ctf-open.c b/libctf/ctf-open.c
index 5230d09a97..77cefc820b 100644
--- a/libctf/ctf-open.c
+++ b/libctf/ctf-open.c
@@ -503,7 +503,7 @@ upgrade_types (ctf_file_t *fp, ctf_header_t *cth)
case CTF_K_UNION:
case CTF_K_ENUM:
case CTF_K_UNKNOWN:
- if (size <= CTF_MAX_SIZE)
+ if ((size_t) size <= CTF_MAX_SIZE)
t2p->ctt_size = size;
else
{
@@ -1317,7 +1317,8 @@ ctf_bufopen (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,

if (hp.cth_flags & CTF_F_COMPRESS)
{
- size_t srclen, dstlen;
+ size_t srclen;
+ uLongf dstlen;
const void *src;
int rc = Z_OK;

@@ -1339,7 +1340,7 @@ ctf_bufopen (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
return (ctf_set_open_errno (errp, ECTF_DECOMPRESS));
}

- if (dstlen != size)
+ if ((size_t) dstlen != size)
{
ctf_dprintf ("zlib inflate short -- got %lu of %lu "
"bytes\n", (unsigned long) dstlen, (unsigned long) size);
@@ -1678,12 +1679,15 @@ ctf_getmodel (ctf_file_t *fp)
return fp->ctf_dmodel->ctd_code;
}

+/* The caller can hang an arbitrary pointer off each ctf_file_t using this
+ function. */
void
ctf_setspecific (ctf_file_t *fp, void *data)
{
fp->ctf_specific = data;
}

+/* Retrieve the arbitrary pointer again. */
void *
ctf_getspecific (ctf_file_t *fp)
{
diff --git a/libctf/ctf-types.c b/libctf/ctf-types.c
index a7fe5d0b18..dc158e2f52 100644
--- a/libctf/ctf-types.c
+++ b/libctf/ctf-types.c
@@ -47,10 +47,10 @@ ctf_member_iter (ctf_file_t *fp, ctf_id_t type, ctf_member_f *func, void *arg)
int rc;

if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
- return CTF_ERR; /* errno is set for us. */
+ return -1; /* errno is set for us. */

if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
- return CTF_ERR; /* errno is set for us. */
+ return -1; /* errno is set for us. */

(void) ctf_get_ctt_size (fp, tp, &size, &increment);
kind = LCTF_INFO_KIND (fp, tp->ctt_info);
@@ -102,10 +102,10 @@ ctf_enum_iter (ctf_file_t *fp, ctf_id_t type, ctf_enum_f *func, void *arg)
int rc;

if ((type = ctf_type_resolve_unsliced (fp, type)) == CTF_ERR)
- return CTF_ERR; /* errno is set for us. */
+ return -1; /* errno is set for us. */

if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
- return CTF_ERR; /* errno is set for us. */
+ return -1; /* errno is set for us. */

if (LCTF_INFO_KIND (fp, tp->ctt_info) != CTF_K_ENUM)
return (ctf_set_errno (ofp, ECTF_NOTENUM));
@@ -406,8 +406,8 @@ ctf_type_size (ctf_file_t *fp, ctf_id_t type)
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)
+ if (ctf_array_info (fp, type, &ar) < 0
+ || (size = ctf_type_size (fp, ar.ctr_contents)) < 0)
return -1; /* errno is set for us. */

return size * ar.ctr_nelems;
@@ -445,7 +445,7 @@ ctf_type_align (ctf_file_t *fp, ctf_id_t type)
case CTF_K_ARRAY:
{
ctf_arinfo_t r;
- if (ctf_array_info (fp, type, &r) == CTF_ERR)
+ if (ctf_array_info (fp, type, &r) < 0)
return -1; /* errno is set for us. */
return (ctf_type_align (fp, r.ctr_contents));
}
@@ -474,7 +474,7 @@ ctf_type_align (ctf_file_t *fp, ctf_id_t type)
for (; n != 0; n--, mp++)
{
ssize_t am = ctf_type_align (fp, mp->ctm_type);
- align = MAX (align, am);
+ align = MAX (align, (size_t) am);
}
}
else
@@ -483,7 +483,7 @@ ctf_type_align (ctf_file_t *fp, ctf_id_t type)
for (; n != 0; n--, lmp++)
{
ssize_t am = ctf_type_align (fp, lmp->ctlm_type);
- align = MAX (align, am);
+ align = MAX (align, (size_t) am);
}
}
}
@@ -495,7 +495,7 @@ ctf_type_align (ctf_file_t *fp, ctf_id_t type)
dmd != NULL; dmd = ctf_list_next (dmd))
{
ssize_t am = ctf_type_align (fp, dmd->dmd_type);
- align = MAX (align, am);
+ align = MAX (align, (size_t) am);
if (kind == CTF_K_STRUCT)
break;
}
@@ -520,7 +520,7 @@ 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 -1; /* errno is set for us. */

return (LCTF_INFO_KIND (fp, tp->ctt_info));
}
@@ -533,13 +533,13 @@ 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_type_kind_unsliced (fp, type)) < 0)
+ return -1;

if (kind == CTF_K_SLICE)
{
if ((type = ctf_type_reference (fp, type)) == CTF_ERR)
- return CTF_ERR;
+ return -1;
kind = ctf_type_kind_unsliced (fp, type);
}

@@ -624,7 +624,7 @@ ctf_type_encoding (ctf_file_t *fp, ctf_id_t type, ctf_encoding_t *ep)
uint32_t data;

if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
- return CTF_ERR; /* errno is set for us. */
+ return -1; /* errno is set for us. */

if ((dtd = ctf_dynamic_type (ofp, type)) != NULL)
{
@@ -790,10 +790,10 @@ ctf_member_info (ctf_file_t *fp, ctf_id_t type, const char *name,
uint32_t kind, n;

if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
- return CTF_ERR; /* errno is set for us. */
+ return -1; /* errno is set for us. */

if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
- return CTF_ERR; /* errno is set for us. */
+ return -1; /* errno is set for us. */

(void) ctf_get_ctt_size (fp, tp, &size, &increment);
kind = LCTF_INFO_KIND (fp, tp->ctt_info);
@@ -847,7 +847,7 @@ ctf_array_info (ctf_file_t *fp, ctf_id_t type, ctf_arinfo_t *arp)
ssize_t increment;

if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
- return CTF_ERR; /* errno is set for us. */
+ return -1; /* errno is set for us. */

if (LCTF_INFO_KIND (fp, tp->ctt_info) != CTF_K_ARRAY)
return (ctf_set_errno (ofp, ECTF_NOTARRAY));
@@ -919,15 +919,15 @@ ctf_enum_value (ctf_file_t * fp, ctf_id_t type, const char *name, int *valp)
uint32_t n;

if ((type = ctf_type_resolve_unsliced (fp, type)) == CTF_ERR)
- return CTF_ERR; /* errno is set for us. */
+ return -1; /* errno is set for us. */

if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
- return CTF_ERR; /* errno is set for us. */
+ return -1; /* 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;
+ return -1;
}

(void) ctf_get_ctt_size (fp, tp, NULL, &increment);
@@ -945,7 +945,7 @@ ctf_enum_value (ctf_file_t * fp, ctf_id_t type, const char *name, int *valp)
}

(void) ctf_set_errno (ofp, ECTF_NOENUMNAM);
- return CTF_ERR;
+ return -1;
}

/* Recursively visit the members of any type. This function is used as the
@@ -965,10 +965,10 @@ ctf_type_rvisit (ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func,
int rc;

if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
- return CTF_ERR; /* errno is set for us. */
+ return -1; /* errno is set for us. */

if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
- return CTF_ERR; /* errno is set for us. */
+ return -1; /* errno is set for us. */

if ((rc = func (name, otype, offset, depth, arg)) != 0)
return rc;
diff --git a/libctf/ctf-util.c b/libctf/ctf-util.c
index 44600467a7..730f358a93 100644
--- a/libctf/ctf-util.c
+++ b/libctf/ctf-util.c
@@ -166,9 +166,9 @@ ctf_set_open_errno (int *errp, int error)
}

/* Store the specified error code into the CTF container, and then return
- CTF_ERR for the benefit of the caller. */
+ CTF_ERR / -1 for the benefit of the caller. */

-long
+unsigned long
ctf_set_errno (ctf_file_t * fp, int err)
{
fp->ctf_errno = err;
diff --git a/libctf/qsort_r.c b/libctf/qsort_r.c
new file mode 100644
index 0000000000..6c334fdaf3
--- /dev/null
+++ b/libctf/qsort_r.c
@@ -0,0 +1,259 @@
+/* Copyright (C) 1991-2019 Free Software Foundation, Inc.
+ This file is part of libctf (imported from Gnulib).
+ Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* If you consider tuning this algorithm, you should consult first:
+ Engineering a sort function; Jon Bentley and M. Douglas McIlroy;
+ Software - Practice and Experience; Vol. 23 (11), 1249-1265, 1993. */
+
+#ifndef _LIBC
+# include <config.h>
+#endif
+
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include "ctf-decls.h"
+
+#ifndef _LIBC
+# define _quicksort qsort_r
+# define __compar_d_fn_t compar_d_fn_t
+typedef int (*compar_d_fn_t) (const void *, const void *, void *);
+#endif
+
+/* Byte-wise swap two items of size SIZE. */
+#define SWAP(a, b, size) \
+ do \
+ { \
+ size_t __size = (size); \
+ char *__a = (a), *__b = (b); \
+ do \
+ { \
+ char __tmp = *__a; \
+ *__a++ = *__b; \
+ *__b++ = __tmp; \
+ } while (--__size > 0); \
+ } while (0)
+
+/* Discontinue quicksort algorithm when partition gets below this size.
+ This particular magic number was chosen to work best on a Sun 4/260. */
+#define MAX_THRESH 4
+
+/* Stack node declarations used to store unfulfilled partition obligations. */
+typedef struct
+ {
+ char *lo;
+ char *hi;
+ } stack_node;
+
+/* The next 4 #defines implement a very fast in-line stack abstraction. */
+/* The stack needs log (total_elements) entries (we could even subtract
+ log(MAX_THRESH)). Since total_elements has type size_t, we get as
+ upper bound for log (total_elements):
+ bits per byte (CHAR_BIT) * sizeof(size_t). */
+#define STACK_SIZE (CHAR_BIT * sizeof(size_t))
+#define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
+#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
+#define STACK_NOT_EMPTY (stack < top)
+
+
+/* Order size using quicksort. This implementation incorporates
+ four optimizations discussed in Sedgewick:
+
+ 1. Non-recursive, using an explicit stack of pointer that store the
+ next array partition to sort. To save time, this maximum amount
+ of space required to store an array of SIZE_MAX is allocated on the
+ stack. Assuming a 32-bit (64 bit) integer for size_t, this needs
+ only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes).
+ Pretty cheap, actually.
+
+ 2. Chose the pivot element using a median-of-three decision tree.
+ This reduces the probability of selecting a bad pivot value and
+ eliminates certain extraneous comparisons.
+
+ 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
+ insertion sort to order the MAX_THRESH items within each partition.
+ This is a big win, since insertion sort is faster for small, mostly
+ sorted array segments.
+
+ 4. The larger of the two sub-partitions is always pushed onto the
+ stack first, with the algorithm then concentrating on the
+ smaller partition. This *guarantees* no more than log (total_elems)
+ stack size is needed (actually O(1) in this case)! */
+
+void
+_quicksort (void *const pbase, size_t total_elems, size_t size,
+ __compar_d_fn_t cmp, void *arg)
+{
+ char *base_ptr = (char *) pbase;
+
+ const size_t max_thresh = MAX_THRESH * size;
+
+ if (total_elems == 0)
+ /* Avoid lossage with unsigned arithmetic below. */
+ return;
+
+ if (total_elems > MAX_THRESH)
+ {
+ char *lo = base_ptr;
+ char *hi = &lo[size * (total_elems - 1)];
+ stack_node stack[STACK_SIZE];
+ stack_node *top = stack;
+
+ PUSH (NULL, NULL);
+
+ while (STACK_NOT_EMPTY)
+ {
+ char *left_ptr;
+ char *right_ptr;
+
+ /* Select median value from among LO, MID, and HI. Rearrange
+ LO and HI so the three values are sorted. This lowers the
+ probability of picking a pathological pivot value and
+ skips a comparison for both the LEFT_PTR and RIGHT_PTR in
+ the while loops. */
+
+ char *mid = lo + size * ((hi - lo) / size >> 1);
+
+ if ((*cmp) ((void *) mid, (void *) lo, arg) < 0)
+ SWAP (mid, lo, size);
+ if ((*cmp) ((void *) hi, (void *) mid, arg) < 0)
+ SWAP (mid, hi, size);
+ else
+ goto jump_over;
+ if ((*cmp) ((void *) mid, (void *) lo, arg) < 0)
+ SWAP (mid, lo, size);
+ jump_over:;
+
+ left_ptr = lo + size;
+ right_ptr = hi - size;
+
+ /* Here's the famous ``collapse the walls'' section of quicksort.
+ Gotta like those tight inner loops! They are the main reason
+ that this algorithm runs much faster than others. */
+ do
+ {
+ while ((*cmp) ((void *) left_ptr, (void *) mid, arg) < 0)
+ left_ptr += size;
+
+ while ((*cmp) ((void *) mid, (void *) right_ptr, arg) < 0)
+ right_ptr -= size;
+
+ if (left_ptr < right_ptr)
+ {
+ SWAP (left_ptr, right_ptr, size);
+ if (mid == left_ptr)
+ mid = right_ptr;
+ else if (mid == right_ptr)
+ mid = left_ptr;
+ left_ptr += size;
+ right_ptr -= size;
+ }
+ else if (left_ptr == right_ptr)
+ {
+ left_ptr += size;
+ right_ptr -= size;
+ break;
+ }
+ }
+ while (left_ptr <= right_ptr);
+
+ /* Set up pointers for next iteration. First determine whether
+ left and right partitions are below the threshold size. If so,
+ ignore one or both. Otherwise, push the larger partition's
+ bounds on the stack and continue sorting the smaller one. */
+
+ if ((size_t) (right_ptr - lo) <= max_thresh)
+ {
+ if ((size_t) (hi - left_ptr) <= max_thresh)
+ /* Ignore both small partitions. */
+ POP (lo, hi);
+ else
+ /* Ignore small left partition. */
+ lo = left_ptr;
+ }
+ else if ((size_t) (hi - left_ptr) <= max_thresh)
+ /* Ignore small right partition. */
+ hi = right_ptr;
+ else if ((right_ptr - lo) > (hi - left_ptr))
+ {
+ /* Push larger left partition indices. */
+ PUSH (lo, right_ptr);
+ lo = left_ptr;
+ }
+ else
+ {
+ /* Push larger right partition indices. */
+ PUSH (left_ptr, hi);
+ hi = right_ptr;
+ }
+ }
+ }
+
+ /* Once the BASE_PTR array is partially sorted by quicksort the rest
+ is completely sorted using insertion sort, since this is efficient
+ for partitions below MAX_THRESH size. BASE_PTR points to the beginning
+ of the array to sort, and END_PTR points at the very last element in
+ the array (*not* one beyond it!). */
+
+#define min(x, y) ((x) < (y) ? (x) : (y))
+
+ {
+ char *const end_ptr = &base_ptr[size * (total_elems - 1)];
+ char *tmp_ptr = base_ptr;
+ char *thresh = min(end_ptr, base_ptr + max_thresh);
+ char *run_ptr;
+
+ /* Find smallest element in first threshold and place it at the
+ array's beginning. This is the smallest array element,
+ and the operation speeds up insertion sort's inner loop. */
+
+ for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size)
+ if ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, arg) < 0)
+ tmp_ptr = run_ptr;
+
+ if (tmp_ptr != base_ptr)
+ SWAP (tmp_ptr, base_ptr, size);
+
+ /* Insertion sort, running from left-hand-side up to right-hand-side. */
+
+ run_ptr = base_ptr + size;
+ while ((run_ptr += size) <= end_ptr)
+ {
+ tmp_ptr = run_ptr - size;
+ while ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, arg) < 0)
+ tmp_ptr -= size;
+
+ tmp_ptr += size;
+ if (tmp_ptr != run_ptr)
+ {
+ char *trav;
+
+ trav = run_ptr + size;
+ while (--trav >= run_ptr)
+ {
+ char c = *trav;
+ char *hi, *lo;
+
+ for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo)
+ *hi = *lo;
+ *hi = c;
+ }
+ }
+ }
+ }
+}
diff --git a/libctf/swap.h b/libctf/swap.h
index 06a9330181..e75e8d408a 100644
--- a/libctf/swap.h
+++ b/libctf/swap.h
@@ -29,13 +29,13 @@

/* Provide our own versions of the byteswap functions. */
inline uint16_t
-bswap_16(uint16_t v)
+bswap_16 (uint16_t v)
{
return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
}

inline uint32_t
-bswap_32(uint32_t v)
+bswap_32 (uint32_t v)
{
return ( ((v & 0xff000000) >> 24)
| ((v & 0x00ff0000) >> 8)
@@ -44,7 +44,13 @@ bswap_32(uint32_t v)
}

inline uint64_t
-bswap_64(uint64_t v)
+bswap_identity_64 (uint64_t v)
+{
+ return v;
+}
+
+inline uint64_t
+bswap_64 (uint64_t v)
{
return ( ((v & 0xff00000000000000ULL) >> 56)
| ((v & 0x00ff000000000000ULL) >> 40)