diff --git a/configure.ac b/configure.ac index 45cd023bb1..3e508571e9 100644 --- a/configure.ac +++ b/configure.ac @@ -108,6 +108,12 @@ AC_ARG_ENABLE([lcov], [use_lcov=yes], [use_lcov=no]) +AC_ARG_ENABLE([glibc-back-compat], + [AS_HELP_STRING([--enable-glibc-back-compat], + [enable backwards compatibility with glibc and libstdc++])], + [use_glibc_compat=$enableval], + [use_glibc_compat=no]) + AC_ARG_WITH([protoc-bindir],[AS_HELP_STRING([--with-protoc-bindir=BIN_DIR],[specify protoc bin path])], [protoc_bin_path=$withval], []) @@ -319,6 +325,21 @@ fi AX_CHECK_LINK_FLAG([[-Wl,--large-address-aware]], [LDFLAGS="$LDFLAGS -Wl,--large-address-aware"]) +if test x$use_glibc_compat != xno; then + + #__fdelt_chk's params and return type have changed from long unsigned int to long int. + # See which one is present here. + AC_MSG_CHECKING(__fdelt_chk type) + AC_TRY_COMPILE([#define __USE_FORTIFY_LEVEL 2 + #include + extern "C" long unsigned int __fdelt_warn(long unsigned int);],[], + [ fdelt_type="long unsigned int"], + [ fdelt_type="long int"]) + AC_MSG_RESULT($fdelt_type) + AC_DEFINE_UNQUOTED(FDELT_TYPE, $fdelt_type,[parameter and return value type for __fdelt_chk]) + +fi + if test x$use_hardening != xno; then AX_CHECK_COMPILE_FLAG([-Wstack-protector],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -Wstack-protector"]) AX_CHECK_COMPILE_FLAG([-fstack-protector-all],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -fstack-protector-all"]) @@ -691,6 +712,7 @@ AM_CONDITIONAL([USE_QRCODE], [test x$use_qr = xyes]) AM_CONDITIONAL([USE_LCOV],[test x$use_lcov == xyes]) AM_CONDITIONAL([USE_COMPARISON_TOOL],[test x$use_comparison_tool != xno]) AM_CONDITIONAL([USE_COMPARISON_TOOL_REORG_TESTS],[test x$use_comparison_tool_reorg_test != xno]) +AM_CONDITIONAL([GLIBC_BACK_COMPAT],[test x$use_glibc_compat = xyes]) AC_DEFINE(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR, [Major version]) AC_DEFINE(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR, [Minor version]) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index 018b6fb26f..1747f531ea 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -41,7 +41,7 @@ script: | cd ../build function do_configure { - ./configure "$@" --enable-upnp-default --prefix=$STAGING --with-protoc-bindir=$STAGING/host/bin --with-boost=$STAGING --disable-maintainer-mode --disable-dependency-tracking PKG_CONFIG_PATH="$STAGING/lib/pkgconfig" CPPFLAGS="-I$STAGING/include ${OPTFLAGS}" LDFLAGS="-L$STAGING/lib ${OPTFLAGS}" CXXFLAGS="-frandom-seed=bitcoin ${OPTFLAGS}" BOOST_CHRONO_EXTRALIBS="-lrt" + ./configure "$@" --enable-upnp-default --prefix=$STAGING --with-protoc-bindir=$STAGING/host/bin --with-boost=$STAGING --disable-maintainer-mode --disable-dependency-tracking PKG_CONFIG_PATH="$STAGING/lib/pkgconfig" CPPFLAGS="-I$STAGING/include ${OPTFLAGS}" LDFLAGS="-L$STAGING/lib ${OPTFLAGS}" CXXFLAGS="-frandom-seed=bitcoin ${OPTFLAGS}" BOOST_CHRONO_EXTRALIBS="-lrt" --enable-glibc-back-compat } # cd bitcoin @@ -60,19 +60,6 @@ script: | make $MAKEOPTS install-strip make $MAKEOPTS clean - # Build fully static versions of bitcoind and bitcoin-cli for older Linux distros - STATIC_BINDIR="$HOME/bindir.static" - mkdir -p $STATIC_BINDIR - # For 32-bit, -pie cannot be used with -static, as invalid executables are generated - # For 64-bit, -pie with -static causes a link error - # Disable hardening in configure and manually pass 'static-safe' hardening flags - OPTFLAGS='-O2 -static -Wstack-protector -fstack-protector-all -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -Wl,-z,relro -Wl,-z,now' - do_configure --bindir=$STATIC_BINDIR --disable-tests --enable-upnp-default --without-gui --disable-hardening - make $MAKEOPTS - make $MAKEOPTS install-strip - cp $STATIC_BINDIR/bitcoind $BINDIR/bitcoind.static - cp $STATIC_BINDIR/bitcoin-cli $BINDIR/bitcoin-cli.static - # sort distribution tar file and normalize user/group/mtime information for deterministic output mkdir -p $OUTDIR/src rm -rf $TEMPDIR diff --git a/src/Makefile.am b/src/Makefile.am index b037ac2c98..215d0319f9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -136,6 +136,11 @@ libbitcoin_common_a_SOURCES = \ version.cpp \ $(BITCOIN_CORE_H) +if GLIBC_BACK_COMPAT +libbitcoin_common_a_SOURCES += compat/glibc_compat.cpp +libbitcoin_common_a_SOURCES += compat/glibcxx_compat.cpp +endif + libbitcoin_cli_a_SOURCES = \ rpcclient.cpp \ $(BITCOIN_CORE_H) diff --git a/src/compat/glibc_compat.cpp b/src/compat/glibc_compat.cpp new file mode 100644 index 0000000000..5b73e6051a --- /dev/null +++ b/src/compat/glibc_compat.cpp @@ -0,0 +1,19 @@ +#include "bitcoin-config.h" +#include +#include + +// Prior to GLIBC_2.14, memcpy was aliased to memmove. +extern "C" void* memmove(void* a, const void* b, size_t c); +extern "C" void* memcpy(void* a, const void* b, size_t c) +{ + return memmove(a, b, c); +} + +extern "C" void __chk_fail (void) __attribute__((__noreturn__)); +extern "C" FDELT_TYPE __fdelt_warn(FDELT_TYPE a) +{ + if (a >= FD_SETSIZE) + __chk_fail (); + return a / __NFDBITS; +} +extern "C" FDELT_TYPE __fdelt_chk(FDELT_TYPE) __attribute__((weak, alias("__fdelt_warn"))); diff --git a/src/compat/glibcxx_compat.cpp b/src/compat/glibcxx_compat.cpp new file mode 100644 index 0000000000..e91376f818 --- /dev/null +++ b/src/compat/glibcxx_compat.cpp @@ -0,0 +1,87 @@ +#include +#include +#include +#include + +#ifndef _GLIBCXX_USE_NOEXCEPT + #define _GLIBCXX_USE_NOEXCEPT throw() +#endif + +namespace std { + +const char* bad_exception::what() const throw() +{ + return "std::bad_exception"; +} + +const char* bad_cast::what() const throw() +{ + return "std::bad_cast"; +} + +const char* bad_alloc::what() const throw() +{ + return "std::bad_alloc"; +} + +namespace __detail +{ +struct _List_node_base +{ + void _M_hook(std::__detail::_List_node_base* const __position) throw () __attribute__((used)) + { + _M_next = __position; + _M_prev = __position->_M_prev; + __position->_M_prev->_M_next = this; + __position->_M_prev = this; + } + void _M_unhook() __attribute__((used)) + { + _List_node_base* const __next_node = _M_next; + _List_node_base* const __prev_node = _M_prev; + __prev_node->_M_next = __next_node; + __next_node->_M_prev = __prev_node; + } + _List_node_base* _M_next; + _List_node_base* _M_prev; +}; +} // namespace detail + +template ostream& ostream::_M_insert(bool); +template ostream& ostream::_M_insert(long); +template ostream& ostream::_M_insert(double); +template ostream& ostream::_M_insert(unsigned long); +template ostream& ostream::_M_insert(const void*); +template ostream& __ostream_insert(ostream&, const char*, streamsize); +template istream& istream::_M_extract(long&); +template istream& istream::_M_extract(unsigned short&); + +out_of_range::~out_of_range() _GLIBCXX_USE_NOEXCEPT { } + +// Used with permission. +// See: https://github.com/madlib/madlib/commit/c3db418c0d34d6813608f2137fef1012ce03043d + +void +ctype::_M_widen_init() const { + char __tmp[sizeof(_M_widen)]; + for (unsigned __i = 0; __i < sizeof(_M_widen); ++__i) + __tmp[__i] = __i; + do_widen(__tmp, __tmp + sizeof(__tmp), _M_widen); + + _M_widen_ok = 1; + // Set _M_widen_ok to 2 if memcpy can't be used. + for (unsigned __i = 0; __i < sizeof(_M_widen); ++__i) + if (__tmp[__i] != _M_widen[__i]) { + _M_widen_ok = 2; + break; + } +} + +void __throw_out_of_range_fmt(const char*, ...) __attribute__((__noreturn__)); +void __throw_out_of_range_fmt(const char* err, ...) +{ + // Safe and over-simplified version. Ignore the format and print it as-is. + __throw_out_of_range(err); +} + +}// namespace std