libctf: look for BSD versus GNU qsort_r signatures

We cannot just look for any declaration of qsort_r, because some
operating systems have a qsort_r that has a different prototype
but which still has a pair of pointers in the right places (the last two
args are interchanged): so use AC_LINK_IFELSE to check for both
known variants of qsort_r(), and swap their args into a consistent order
in a suitable inline function.  (The code for this is taken almost
unchanged from gnulib.)

(Now we are not using AC_LIBOBJ any more, we can use a better name for
the qsort_r replacement as well.)

libctf/
	* qsort_r.c: Rename to...
	* ctf-qsort_r.c: ... this.
	(_quicksort): Define to ctf_qsort_r.
	* ctf-decls.h (qsort_r): Remove.
	(ctf_qsort_r): Add.
	(struct ctf_qsort_arg): New, transport the real ARG and COMPAR.
	(ctf_qsort_compar_thunk): Rearrange the arguments to COMPAR.
	* Makefile.am (libctf_a_LIBADD): Remove.
	(libctf_a_SOURCES): New, add ctf-qsort_r.c.
	* ctf-archive.c (ctf_arc_write): Call ctf_qsort_r, not qsort_r.
	* ctf-create.c (ctf_update): Likewise.
	* configure.ac: Check for BSD versus GNU qsort_r signature.
	* Makefile.in: Regenerate.
	* config.h.in: Likewise.
	* configure: Likewise.
This commit is contained in:
Nick Alcock 2019-06-03 14:02:09 +01:00
parent 941accce38
commit 6b22174ff1
10 changed files with 237 additions and 86 deletions

View File

@ -1,3 +1,21 @@
2019-06-04 Nick Alcock <nick.alcock@oracle.com>
* qsort_r.c: Rename to...
* ctf-qsort_r.c: ... this.
(_quicksort): Define to ctf_qsort_r.
* ctf-decls.h (qsort_r): Remove.
(ctf_qsort_r): Add.
(struct ctf_qsort_arg): New, transport the real ARG and COMPAR.
(ctf_qsort_compar_thunk): Rearrange the arguments to COMPAR.
* Makefile.am (libctf_a_LIBADD): Remove.
(libctf_a_SOURCES): New, add ctf-qsort_r.c.
* ctf-archive.c (ctf_arc_write): Call ctf_qsort_r, not qsort_r.
* ctf-create.c (ctf_update): Likewise.
* configure.ac: Check for BSD versus GNU qsort_r signature.
* Makefile.in: Regenerate.
* config.h.in: Likewise.
* configure: Likewise.
2019-06-03 Nick Alcock <nick.alcock@oracle.com>
* ctf-dump.c (ctf_dump_funcs): Free in the right place.

View File

@ -35,4 +35,6 @@ 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)
if NEED_CTF_QSORT_R
libctf_a_SOURCES += ctf-qsort_r.c
endif

View File

@ -104,6 +104,7 @@ POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
@NEED_CTF_QSORT_R_TRUE@am__append_1 = ctf-qsort_r.c
subdir = .
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \
@ -128,12 +129,17 @@ 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_DEPENDENCIES = $(LIBOBJS)
libctf_a_LIBADD =
am__libctf_a_SOURCES_DIST = 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 \
ctf-qsort_r.c
@NEED_CTF_QSORT_R_TRUE@am__objects_1 = ctf-qsort_r.$(OBJEXT)
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)
ctf-types.$(OBJEXT) ctf-util.$(OBJEXT) $(am__objects_1)
libctf_a_OBJECTS = $(am_libctf_a_OBJECTS)
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
@ -164,7 +170,7 @@ 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)
DIST_SOURCES = $(am__libctf_a_SOURCES_DIST)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@ -196,7 +202,7 @@ 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 \
ChangeLog qsort_r.c
ChangeLog
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
@ -323,11 +329,10 @@ 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@ $(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)
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 \
$(am__append_1)
all: config.h
$(MAKE) $(AM_MAKEFLAGS) all-am
@ -396,7 +401,6 @@ 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@
@ -407,6 +411,7 @@ distclean-compile:
@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-qsort_r.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@
@ -687,7 +692,7 @@ clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf $(DEPDIR) ./$(DEPDIR)
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-hdr distclean-tags
@ -735,7 +740,7 @@ installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf $(top_srcdir)/autom4te.cache
-rm -rf $(DEPDIR) ./$(DEPDIR)
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic

View File

@ -9,10 +9,6 @@
/* 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
@ -31,6 +27,15 @@
/* Define to 1 if you have the `pread' function. */
#undef HAVE_PREAD
/* Define to 1 if you have the `qsort_r' function. */
#undef HAVE_QSORT_R
/* Whether a qsort_r exists with a void *arg as its last arg. */
#undef HAVE_QSORT_R_ARG_LAST
/* Whether a qsort_r exists with the compar function as its last arg. */
#undef HAVE_QSORT_R_COMPAR_LAST
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H

163
libctf/configure vendored
View File

@ -620,10 +620,13 @@ ac_includes_default="\
#endif"
ac_header_list=
ac_func_list=
ac_subst_vars='am__EXEEXT_FALSE
am__EXEEXT_TRUE
LTLIBOBJS
LIBOBJS
NEED_CTF_QSORT_R_FALSE
NEED_CTF_QSORT_R_TRUE
zlibinc
zlibdir
ac_libctf_warn_cflags
@ -1809,52 +1812,6 @@ $as_echo "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_func
# 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.
@ -2142,6 +2099,7 @@ 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"
as_fn_append ac_func_list " qsort_r"
# Check that the precious variables saved in the cache have kept the same
# value.
ac_cache_corrupted=false
@ -6401,23 +6359,108 @@ _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
for ac_func in $ac_func_list
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
case " $LIBOBJS " in
*" qsort_r.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS qsort_r.$ac_objext"
;;
fi
done
if test $ac_cv_func_qsort_r = yes; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for qsort_r signature" >&5
$as_echo_n "checking for qsort_r signature... " >&6; }
if ${ac_cv_libctf_qsort_r_signature+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#undef qsort_r
#include <stdlib.h>
void qsort_r (void *, size_t, size_t,
int (*) (void const *, void const *,
void *),
void *);
void (*p) (void *, size_t, size_t,
int (*) (void const *, void const *,
void *),
void *) = qsort_r;
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_libctf_qsort_r_signature=GNU
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#undef qsort_r
#include <stdlib.h>
void qsort_r (void *, size_t, size_t, void *,
int (*) (void *,
void const *,
void const *));
void (*p) (void *, size_t, size_t, void *,
int (*) (void *, void const *,
void const *)) = qsort_r;
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_libctf_qsort_r_signature=BSD
else
ac_cv_libctf_qsort_r_signature=unknown
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
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_qsort_r_signature" >&5
$as_echo "$ac_cv_libctf_qsort_r_signature" >&6; }
fi
case x$ac_cv_libctf_qsort_r_signature in
xGNU)
$as_echo "#define HAVE_QSORT_R_ARG_LAST 1" >>confdefs.h
;;
xBSD)
$as_echo "#define HAVE_QSORT_R_COMPAR_LAST 1" >>confdefs.h
;;
*) ac_cv_libctf_qsort_r_signature=unknown;;
esac
if test "${ac_cv_libctf_qsort_r_signature}" = unknown; then
NEED_CTF_QSORT_R_TRUE=
NEED_CTF_QSORT_R_FALSE='#'
else
NEED_CTF_QSORT_R_TRUE='#'
NEED_CTF_QSORT_R_FALSE=
fi
ac_config_files="$ac_config_files Makefile"
@ -6561,6 +6604,10 @@ if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${NEED_CTF_QSORT_R_TRUE}" && test -z "${NEED_CTF_QSORT_R_FALSE}"; then
as_fn_error $? "conditional \"NEED_CTF_QSORT_R\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
: "${CONFIG_STATUS=./config.status}"
ac_write_fail=0

View File

@ -90,8 +90,48 @@ fi
AC_C_BIGENDIAN
AC_CHECK_HEADERS(byteswap.h endian.h)
AC_CHECK_FUNCS(pread)
AC_CHECK_DECLS([qsort_r])
AC_LIBOBJ([qsort_r])
dnl Check for qsort_r. (Taken from gnulib.)
AC_CHECK_FUNCS_ONCE([qsort_r])
if test $ac_cv_func_qsort_r = yes; then
AC_CACHE_CHECK([for qsort_r signature], [ac_cv_libctf_qsort_r_signature],
[AC_LINK_IFELSE(
[AC_LANG_PROGRAM([[#undef qsort_r
#include <stdlib.h>
void qsort_r (void *, size_t, size_t,
int (*) (void const *, void const *,
void *),
void *);
void (*p) (void *, size_t, size_t,
int (*) (void const *, void const *,
void *),
void *) = qsort_r;
]])],
[ac_cv_libctf_qsort_r_signature=GNU],
[AC_LINK_IFELSE(
[AC_LANG_PROGRAM([[#undef qsort_r
#include <stdlib.h>
void qsort_r (void *, size_t, size_t, void *,
int (*) (void *,
void const *,
void const *));
void (*p) (void *, size_t, size_t, void *,
int (*) (void *, void const *,
void const *)) = qsort_r;
]])],
[ac_cv_libctf_qsort_r_signature=BSD],
[ac_cv_libctf_qsort_r_signature=unknown])])])
fi
case x$ac_cv_libctf_qsort_r_signature in
xGNU) AC_DEFINE([HAVE_QSORT_R_ARG_LAST], 1,
[Whether a qsort_r exists with a void *arg as its last arg.]);;
xBSD) AC_DEFINE([HAVE_QSORT_R_COMPAR_LAST], 1,
[Whether a qsort_r exists with the compar function as its last arg.]);;
*) ac_cv_libctf_qsort_r_signature=unknown;;
esac
AM_CONDITIONAL(NEED_CTF_QSORT_R, test "${ac_cv_libctf_qsort_r_signature}" = unknown)
AC_CONFIG_FILES(Makefile)
AC_CONFIG_HEADERS(config.h)

View File

@ -169,10 +169,11 @@ ctf_arc_write (const char *file, ctf_file_t ** ctf_files, size_t ctf_file_cnt,
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);
ctf_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. */

View File

@ -344,7 +344,7 @@ ctf_update (ctf_file_t *fp)
}
assert (i == nvars);
qsort_r (dvarents, nvars, sizeof (ctf_varent_t), ctf_sort_var, s0);
ctf_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);

View File

@ -22,12 +22,45 @@
#include "config.h"
#if !HAVE_DECL_QSORT_R
#include <stddef.h>
void qsort_r (void *base, size_t nmemb, size_t size,
#include <stdlib.h>
#if HAVE_QSORT_R_ARG_LAST
static inline void
ctf_qsort_r (void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *, void *),
void *arg)
{
qsort_r (base, nmemb, size, compar, arg);
}
#elif HAVE_QSORT_R_COMPAR_LAST
struct ctf_qsort_arg
{
int (*compar) (const void *, const void *, void *);
void *arg;
};
static int
ctf_qsort_compar_thunk (void *arg, const void *a, const void *b)
{
struct ctf_qsort_arg *qsort_arg = (struct ctf_qsort_arg *) arg;
return qsort_arg->compar (a, b, arg);
}
static inline void
ctf_qsort_r (void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *, void *),
void *arg)
{
struct ctf_qsort_arg thunk = { compar, arg };
qsort_r (base, nmemb, size, &thunk, ctf_qsort_compar_thunk);
}
#else
void ctf_qsort_r (void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *, void *),
void *arg);
#endif /* !HAVE_DECL_QSORT_R */
#endif
#undef MAX
#undef MIN

View File

@ -30,7 +30,7 @@
#include "ctf-decls.h"
#ifndef _LIBC
# define _quicksort qsort_r
# define _quicksort ctf_qsort_r
# define __compar_d_fn_t compar_d_fn_t
typedef int (*compar_d_fn_t) (const void *, const void *, void *);
#endif