Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Workaround issues with ld from binutils 2.29 #266

Merged
merged 7 commits into from
Dec 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@ aclocal.m4
autom4te.cache/
config.status
configure
conftest.*
.libs

# since we use subdir-objects as automake option
.dirstamp

# ignore "libtoolized" m4 files, but keep our (custom-prefixed) ones
/m4/*
!/m4/ax_*.m4
Expand All @@ -25,6 +29,9 @@ configure
/.tarball-version
/tag-*

/lib/qblog_script.ld
# already captured with wildcard: /lib/qblog_script.la

libtool
.version
libqb.spec
Expand All @@ -35,4 +42,12 @@ abi_dumps
TAGS
*~
test-driver
tests/*.trs

/tests/**/*.real
/tests/**/*.trs
/tests/functional/log_callsite_bench.c
/tests/functional/**/log_callsite_bench_section*.c
/tests/functional/**/log_client
/tests/functional/**/log_interlib_client
/tests/functional/_pkgs
/tests/functional/_results
4 changes: 3 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ addons:
script: RPMBUILDOPTS_="--nodeps --define '_without_check 1'";
./autogen.sh
&& ./configure
&& make distcheck CPPFLAGS=-Dci_dump_shm_usage VERBOSE=1
&& make -C lib V=1
&& make -C tests/functional/log_internal V=1 check
&& make V=1 CPPFLAGS=-Dci_dump_shm_usage distcheck
&& sed "s|RPMBUILDOPTS =|\\0 ${RPMBUILDOPTS_}|" Makefile | make -f- rpm

after_failure:
Expand Down
2 changes: 2 additions & 0 deletions check
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ check_nosection() {
echo "checking nosection"
echo "======================="
# no __attribute__((section))
# NOTE: alternatively CPPFLAGS=-DQB_KILL_ATTRIBUTE_SECTION, but
# that won't shortcut many initial/configure decisions
check "ac_cv_link_attribute_section=no"
}

Expand Down
177 changes: 161 additions & 16 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ AC_CONFIG_SRCDIR([lib/ringbuffer.c])
AC_CONFIG_HEADERS([include/config.h include/qb/qbconfig.h])
AC_USE_SYSTEM_EXTENSIONS

AM_INIT_AUTOMAKE([-Wno-portability dist-xz])
AM_INIT_AUTOMAKE([-Wno-portability dist-xz subdir-objects])
dnl automake >= 1.11 offers --enable-silent-rules for suppressing the output from
dnl normal compilation. When a failure occurs, it will then display the full
dnl command line
Expand Down Expand Up @@ -77,6 +77,10 @@ AC_CHECK_PROGS([DOXYGEN], [doxygen])
AM_CONDITIONAL(HAVE_DOXYGEN, test -n "${DOXYGEN}")
AC_CHECK_PROGS([SPLINT], [splint])
AM_CONDITIONAL(HAVE_SPLINT, test -n "${SPLINT}")
AC_CHECK_TOOLS([NM], [eu-nm nm], [:])
AC_CHECK_TOOLS([READELF], [eu-readelf readelf], [:])
AM_PATH_PYTHON([2.6],, [:])
AM_CONDITIONAL([HAVE_PYTHON], [test "$PYTHON" != :])

## local helper functions

Expand Down Expand Up @@ -501,6 +505,14 @@ AC_ARG_ENABLE([debug],
AC_ARG_ENABLE([coverage],
[AS_HELP_STRING([--enable-coverage],[coverage analysis of the codebase])])

AC_ARG_ENABLE([interlib-deps],
[AS_HELP_STRING([--disable-interlib-deps],
[disable inter-library dependencies (might break builds)])])

AC_ARG_ENABLE([nosection-fallback],
[AS_HELP_STRING([--enable-nosection-fallback],
[allow (logging compat-breaking?) fallback when orphan section dead-ended])])

AC_ARG_ENABLE([slow-tests],
[AS_HELP_STRING([--enable-slow-tests],[build and run slow tests])])

Expand Down Expand Up @@ -609,6 +621,19 @@ else
COVERAGE_LDFLAGS=""
fi

# --- inter-library dependencies ---
# because of debian/ubuntu swimming against the stream
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=702737,
# override the libtool variable by force because the current
# arrangement relies on transitive dependency propagation
AC_MSG_NOTICE([Enabling inter-library dependencies: $enable_interlib_deps])
if test "x${enable_interlib_deps}" = xno; then
link_all_deplibs=no
else
link_all_deplibs=yes
fi

# --- slow tests ---
if test "x${enable_slow_tests}" = xyes ; then
AC_DEFINE([HAVE_SLOW_TESTS], 1,[have slow tests])
AC_MSG_NOTICE([Enabling Slow tests])
Expand All @@ -618,28 +643,141 @@ AC_SUBST(HAVE_SLOW_TESTS)

# --- callsite sections ---
if test "x${GCC}" = xyes; then
AX_SAVE_FLAGS
AC_MSG_CHECKING([whether GCC supports __attribute__((section()) + ld supports orphan sections])
if test "x${ac_cv_link_attribute_section}" = x ; then
AC_TRY_LINK([#include <assert.h>
extern void * __start___verbose, * __stop___verbose;],
[static int my_var __attribute__((section("__verbose"))) = 5;
if (__start___verbose == __stop___verbose) assert(0);
if (my_var == 5) return 0;
else return -1;
],
[gcc_has_attribute_section=yes],
[gcc_has_attribute_section=no])
LDFLAGS="${LDFLAGS_save} -shared -fPIC" # we are compiling shared lib
AC_LINK_IFELSE(
[AC_LANG_SOURCE(
[[#include <assert.h>
extern int __start___verbose[], __stop___verbose[];
int test(void) {
static int my_var __attribute__((section("__verbose"))) = 3;
assert("L:non-empty data section"
&& __start___verbose != __stop___verbose);
assert("L:no data section value loss"
&& my_var == 3 /* for 2.29.1+ */);
return *((int *) __start___verbose); }]]
)],
[gcc_has_attribute_section=yes; cp "conftest${ac_exeext}" "conftest.so"],
[gcc_has_attribute_section=no]
)
AX_RESTORE_FLAGS
else
gcc_has_attribute_section=${ac_cv_link_attribute_section}
fi

AC_MSG_RESULT($gcc_has_attribute_section)
if test $gcc_has_attribute_section = yes; then
AC_DEFINE([QB_HAVE_ATTRIBUTE_SECTION], 1,
[Enabling code using __attribute__((section))])
PACKAGE_FEATURES="$PACKAGE_FEATURES attribute-section"

# in the failing case (e.g. with ld from binutils 2.29), it's likely the
# following will fail readily in linkage (hidden symbol `__stop___verbose'
# in conftest is referenced by DSO), but keep the sensible test
# (in-executable symbol is expected to be propagated into the library,
# and to draw the full circle back to the executable through standard
# return value passing (respectively no-exec probing to spot the issue);
# -rpath passed because LD_LIBRARY_PATH exporting is unwieldy here);
# moreover, "my_var" == 3 assertion above (respectively checking if the
# boundary symbol visibility differs from DEFAULT in readelf output) is
# necessary so that binutils 2.29.1+ will not slip other parts of the
# overall is-workaround-needed harness, as it restored some (but not
# all) of the original behaviour, but the workaround is still provably
# needed
if test "x${gcc_has_attribute_section}" = xyes; then
AC_MSG_CHECKING([whether linker emits global boundary symbols for orphan sections])
LIBS="${LIBS} -L. -l:conftest${shrext_cmds} -Wl,-rpath=$(pwd)"
dnl could be turned to AC_TRY_RUN (first assertion is equivalent to
dnl the further check in action-if-true), but that would prevent
dnl cross-building
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <assert.h>
extern int __start___verbose[], __stop___verbose[];
int test(void);]],
[[static int my_var __attribute__((section("__verbose"))) = 5;
assert("E:non-empty data section"
&& __start___verbose != __stop___verbose);
assert("E:no data section value loss"
&& my_var == test() /*5?*/);]]
)],
[# alternatively something like (but requires number parsing):
# readelf -SW "conftest${ac_exeext}" \
# | sed -n '/__verbose/s/^\s*//p' | tr -s ' ' | cut -d" " -f6
verbose_start_addr=$(${NM} -g --portability -- "conftest${ac_exeext}" \
| grep __start___verbose | cut -d" " -f 3)
verbose_stop_addr=$(${NM} -g --portability -- "conftest${ac_exeext}" \
| grep __stop___verbose | cut -d" " -f 3)
test "${verbose_start_addr}" = "${verbose_stop_addr}" \
&& gcc_has_attribute_section_visible=no \
|| { verbose_start_type=$(${READELF} -s backup \
| sed -n '/__start___verbose/{s/^\s*//p;q}' \
| tr -s ' ' \
| cut -d" " -f6)
test "${verbose_start_type}" = DEFAULT \
&& gcc_has_attribute_section_visible=yes \
|| gcc_has_attribute_section_visible=no; }],
[gcc_has_attribute_section_visible=no]
)
AX_RESTORE_FLAGS
AC_MSG_RESULT($gcc_has_attribute_section_visible)
rm -f "conftest${shrext_cmds}"

if test "x${gcc_has_attribute_section_visible}" = xno; then
# check if the linker script based workaround is
# feasible at all, otherwise fallback to using no
# section attribute while making some noise about it
# as combining with-without accustomed logging
# participants is currently uncharted waters
AC_MSG_CHECKING([whether linker workaround for orphan sections usable])
>conftest.ld cat <<-EOF
SECTIONS {
__verbose : {
__start___verbose = .;
*(__verbose);
__stop___verbose = .;
}
}
EOF
LDFLAGS="${LDFLAGS} -Wl,conftest.ld"
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <assert.h>
extern int __start___verbose[], __stop___verbose[];
int test(void);]],
[[static int my_var __attribute__((section("__verbose"))) = 5;
assert("E:non-empty data section"
&& __start___verbose != __stop___verbose);
assert("E:no data section value loss"
&& my_var == 5);]]
)],
[],
[gcc_has_attribute_section=no]
)
AX_RESTORE_FLAGS
AC_MSG_RESULT([$gcc_has_attribute_section])
rm -f "conftest.ld"
fi

if test "x${gcc_has_attribute_section}" = xyes; then
AC_DEFINE([QB_HAVE_ATTRIBUTE_SECTION], 1,
[Enabling code using __attribute__((section))])
AC_SUBST([client_dlopen_LIBS],[$dlopen_LIBS])
if test "x${gcc_has_attribute_section_visible}" = xyes; then
PACKAGE_FEATURES="$PACKAGE_FEATURES attribute-section"
else
AC_DEFINE([QB_NEED_ATTRIBUTE_SECTION_WORKAROUND], 1,
[Enabling code using __attribute__((section))])
PACKAGE_FEATURES="$PACKAGE_FEATURES attribute-section-workaround"
fi
elif test "x${enable_nosection_fallback}" = xyes; then
AC_MSG_NOTICE([Falling back to not using orphan section])
else
AC_MSG_ERROR([Would use section attribute, cannot; see --enable-nosection-fallback])
fi
fi
fi
AM_CONDITIONAL(HAVE_GCC_ATTRIBUTE_SECTION, [test "x${gcc_has_attribute_section}" = xyes])
AM_CONDITIONAL(NEED_GCC_ATTRIBUTE_SECTION_WORKAROUND,
[test "x${gcc_has_attribute_section}" = xyes \
&& test "x${gcc_has_attribute_section_visible}" != xyes])

# --- ansi ---
if test "x${enable_ansi}" = xyes && \
Expand Down Expand Up @@ -713,12 +851,19 @@ AC_CONFIG_FILES([Makefile
lib/libqb.pc
tools/Makefile
tests/Makefile
tests/functional/Makefile
tests/functional/log_external/Makefile
tests/functional/log_internal/Makefile
tests/test.conf
examples/Makefile
docs/Makefile
docs/common.dox
docs/html.dox
docs/man.dox])
docs/man.dox
lib/qblog_script.la:lib/qblog_script.la.in])

AC_CONFIG_LINKS([lib/qblog_script_noop.ld:lib/qblog_script_noop.ld
tests/functional/GNUmakefile:tests/functional/GNUmakefile])

AC_OUTPUT

Expand Down
7 changes: 6 additions & 1 deletion include/qb/qbconfig.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,12 @@
/* Enabling code using __attribute__((section)) */
#undef QB_HAVE_ATTRIBUTE_SECTION

/* versioning info: MAJOR, MINOR, MICRO, and REST components */
/* versioning info: MAJOR, MINOR, MICRO, and REST components;
note that static compile-time info is not that useful as consulting
the respectively named members of qb_version struct constant under
@c qb_ver identifier (or @c qb_ver_str equivalent of the local
upper-cased value) directly from libqb in run-time (see qbutil.h),
but that was only introduced after v1.0.2 */
#undef QB_VER_MAJOR
#undef QB_VER_MINOR
#undef QB_VER_MICRO
Expand Down
Loading