From a0486bac41d6ce47f27795a5abbca5cc53ddba00 Mon Sep 17 00:00:00 2001 From: "Jose E. Marchesi" Date: Fri, 31 May 2019 11:10:51 +0200 Subject: [PATCH] libctf: fix a number of build problems found on Solaris and NetBSD - Use of nonportable - Use of qsort_r - Use of zlib without appropriate magic to pull in the binutils zlib - Use of off64_t without checking (fixed by dropping the unused fields that need off64_t entirely) - 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 All fixed, using code from gnulib where possible. Relatedly, set cts_size in a couple of places it was missed (string table and symbol table loading upon ctf_bfdopen()). binutils/ * objdump.c (make_ctfsect): Drop cts_type, cts_flags, and cts_offset. * readelf.c (shdr_to_ctf_sect): Likewise. include/ * ctf-api.h (ctf_sect_t): Drop cts_type, cts_flags, and cts_offset. (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, 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 . (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. Drop cts_type, cts_flags and cts_offset. (ctf_arc_write): Drop debugging dependent on the size of off_t. * ctf-create.c: Provide a definition of roundup if not defined. (ctf_create): Drop cts_type, cts_flags and cts_offset. (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. * ctf-open-bfd.c (ctf_bfdopen): Drop cts_type, cts_flags and cts_offset. (ctf_simple_open): Likewise. (ctf_bfdopen_ctfsect): Likewise. Set cts_size properly. * Makefile.in: Regenerate. * aclocal.m4: Likewise. * config.h: Likewise. * configure: Likewise. --- binutils/ChangeLog | 6 + binutils/objdump.c | 3 - binutils/readelf.c | 3 - include/ChangeLog | 7 + include/ctf-api.h | 12 +- libctf/ChangeLog | 67 +++++++++ libctf/Makefile.am | 9 +- libctf/Makefile.in | 24 +++- libctf/aclocal.m4 | 1 + libctf/config.h.in | 22 +++ libctf/configure | 322 +++++++++++++++++++++++++++++++++++++++++- libctf/configure.ac | 6 +- libctf/ctf-archive.c | 8 +- libctf/ctf-create.c | 50 ++++--- libctf/ctf-decls.h | 37 +++++ libctf/ctf-dump.c | 20 +-- libctf/ctf-endian.h | 37 +++++ libctf/ctf-impl.h | 5 +- libctf/ctf-labels.c | 8 +- libctf/ctf-lookup.c | 4 +- libctf/ctf-open-bfd.c | 11 +- libctf/ctf-open.c | 13 +- libctf/ctf-types.c | 48 +++---- libctf/ctf-util.c | 4 +- libctf/qsort_r.c | 259 +++++++++++++++++++++++++++++++++ libctf/swap.h | 12 +- 26 files changed, 883 insertions(+), 115 deletions(-) create mode 100644 libctf/ctf-decls.h create mode 100644 libctf/ctf-endian.h create mode 100644 libctf/qsort_r.c diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 04710e3e1de..950dee7af50 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,9 @@ +2019-05-30 Nick Alcock + + * objdump.c (make_ctfsect): Drop cts_type, cts_flags, and + cts_offset. + * readelf.c (shdr_to_ctf_sect): Likewise. + 2019-05-30 Nick Clifton PR 24627 diff --git a/binutils/objdump.c b/binutils/objdump.c index 382ba35855c..b9d08f70f95 100644 --- a/binutils/objdump.c +++ b/binutils/objdump.c @@ -3240,10 +3240,7 @@ make_ctfsect (const char *name, bfd_byte *data, ctf_sect_t ctfsect; ctfsect.cts_name = name; - ctfsect.cts_type = SHT_PROGBITS; - ctfsect.cts_flags = 0; ctfsect.cts_entsize = 1; - ctfsect.cts_offset = 0; ctfsect.cts_size = size; ctfsect.cts_data = data; diff --git a/binutils/readelf.c b/binutils/readelf.c index cfa2df5614c..8e2902fdcac 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -13829,11 +13829,8 @@ 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; } diff --git a/include/ChangeLog b/include/ChangeLog index 05083763b1a..1f216b38218 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,10 @@ +2019-05-29 Nick Alcock + + * ctf-api.h (ctf_sect_t): Drop cts_type, cts_flags, and cts_offset. + (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 * ctf-api.h (ctf_dump_decorate_f): New. diff --git a/include/ctf-api.h b/include/ctf-api.h index 822b3bf5a9a..3acbc91b9ae 100644 --- a/include/ctf-api.h +++ b/include/ctf-api.h @@ -43,7 +43,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. */ @@ -60,12 +60,9 @@ struct bfd; 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. */ @@ -125,9 +122,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 879aeed38f7..d059d58d19b 100644 --- a/libctf/ChangeLog +++ b/libctf/ChangeLog @@ -1,3 +1,70 @@ +2019-05-29 Nick Alcock + + * Makefile.am (ZLIB): New. + (ZLIBINC): Likewise. + (AM_CFLAGS): Use them. + (libctf_a_LIBADD): New, for LIBOBJS. + * configure.ac: Check for zlib, endian.h, 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 . + (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. Drop cts_type, + cts_flags and cts_offset. + (ctf_arc_write): Drop debugging dependent on the size of off_t. + * ctf-create.c: Provide a definition of roundup if not defined. + (ctf_create): Drop cts_type, cts_flags and cts_offset. + (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. + * ctf-open-bfd.c (ctf_bfdopen): Drop cts_type, cts_flags and + cts_offset. + (ctf_simple_open): Likewise. + (ctf_bfdopen_ctfsect): Likewise. Set cts_size properly. + * Makefile.in: Regenerate. + * aclocal.m4: Likewise. + * config.h: Likewise. + * configure: Likewise. + 2019-05-28 Nick Alcock * configure.in: Check for bfd_section_from_elf_index. diff --git a/libctf/Makefile.am b/libctf/Makefile.am index 5fe2c95901d..49c9f5280a9 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 b0afa5b80d5..c2cada66167 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 d792e62dfb3..074f03638fc 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 829201033ea..0ecb5bb7211 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 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 header file. */ +#undef HAVE_ENDIAN_H + /* Define to 1 if you have the `getpagesize' function. */ #undef HAVE_GETPAGESIZE @@ -94,6 +104,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 1c0340125a0..4fb44eb2cc6 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,52 @@ $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. @@ -6031,6 +6085,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,12 +6153,237 @@ $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 + #include + +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 + #include + +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 defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +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 + +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 @@ -6105,6 +6401,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 +6561,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 2df10935c05..8fd5388d2a0 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,11 @@ 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_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 ab658fd351c..a238edb66ba 100644 --- a/libctf/ctf-archive.c +++ b/libctf/ctf-archive.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include "ctf-endian.h" #include #include #include @@ -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,16 +511,13 @@ 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); 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, symsect, strsect, errp); if (fp) diff --git a/libctf/ctf-create.c b/libctf/ctf-create.c index 5409ca4bb4d..227f62d8fd7 100644 --- a/libctf/ctf-create.c +++ b/libctf/ctf-create.c @@ -23,6 +23,10 @@ #include #include +#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 @@ -67,12 +71,9 @@ ctf_create (int *errp) } 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; @@ -812,7 +813,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 +844,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 +1176,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 +1305,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 +1335,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 +1360,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 +1370,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 +1402,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 +1427,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 +1453,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 +1473,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 +1483,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 +1551,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 +1756,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 +1803,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 +1820,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 +1850,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 00000000000..5e9ede48099 --- /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 + . */ + +#ifndef _CTF_DECLS_H +#define _CTF_DECLS_H + +#include "config.h" + +#if !HAVE_DECL_QSORT_R +#include +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 28f31e4872a..c2ed791eea6 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 00000000000..ec177d1bdd8 --- /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 + . */ + +#ifndef _CTF_ENDIAN_H +#define _CTF_ENDIAN_H + +#include "config.h" +#include +#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 363b62de7db..fa9c5749414 100644 --- a/libctf/ctf-impl.h +++ b/libctf/ctf-impl.h @@ -21,7 +21,8 @@ #define _CTF_IMPL_H #include "config.h" -#include +#include +#include "ctf-decls.h" #include #include #include @@ -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 9b9fffea4ed..1755b9720a6 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 7ea46a7295b..ab12715f4b1 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-bfd.c b/libctf/ctf-open-bfd.c index 5e34d123699..76b7f9d1629 100644 --- a/libctf/ctf-open-bfd.c +++ b/libctf/ctf-open-bfd.c @@ -97,10 +97,7 @@ ctf_bfdopen (struct bfd *abfd, int *errp) } 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; @@ -158,10 +155,8 @@ ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_, } 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_size = bfd_section_size (abfd, str_asect); strsect.cts_entsize = strhdr->sh_size; - strsect.cts_offset = strhdr->sh_offset; strsectp = &strsect; if (!bfd_malloc_and_get_section (abfd, sym_asect, &contents)) @@ -172,11 +167,9 @@ ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_, } 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_size = bfd_section_size (abfd, sym_asect); symsect.cts_data = contents; - symsect.cts_offset = symhdr->sh_offset; symsectp = &symsect; } } diff --git a/libctf/ctf-open.c b/libctf/ctf-open.c index 5230d09a97f..1a517a140ca 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 { @@ -1170,10 +1170,7 @@ ctf_file_t *ctf_simple_open (const char *ctfsect, size_t ctfsect_size, 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) { @@ -1317,7 +1314,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 +1337,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 +1676,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 a7fe5d0b184..dc158e2f52b 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 44600467a7e..730f358a931 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 00000000000..6c334fdaf39 --- /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 + . */ + +/* 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 +#endif + +#include +#include +#include +#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 06a93301813..e75e8d408a9 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) -- 2.30.2