From patchwork Thu Aug 7 03:47:23 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Frysinger X-Patchwork-Id: 2334 Received: (qmail 30492 invoked by alias); 7 Aug 2014 03:47:28 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 30482 invoked by uid 89); 7 Aug 2014 03:47:27 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.4 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, SPF_PASS autolearn=ham version=3.3.2 X-HELO: smtp.gentoo.org From: Mike Frysinger To: libc-alpha@sourceware.org Subject: [PATCH] detect broken linker handling of __ehdr_start Date: Wed, 6 Aug 2014 23:47:23 -0400 Message-Id: <1407383243-30362-1-git-send-email-vapier@gentoo.org> In-Reply-To: <20140311222933.CC24274474@topped-with-meat.com> References: <20140311222933.CC24274474@topped-with-meat.com> Older versions of ld on ia64 support __ehdr_start, but generate relocs when they shouldn't. This causes the ld.so to not run because it tries to resolve the __ehdr_start symbol (but it's not exported). 2014-08-06 Mike Frysinger * configure.ac: Change __ehdr_start code to dereference the struct. Run readelf on the output to look for relocations. * configure: Regenerated. --- Tested ia64 binutils 2.23.2 & 2.24, and x86_64 binutils 2.23.2 & 2.24. configure | 26 ++++++++++++++++++++------ configure.ac | 23 ++++++++++++++++++----- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/configure b/configure index 646e0bc..86ba307 100755 --- a/configure +++ b/configure @@ -6965,8 +6965,11 @@ if test $libc_cv_predef_stack_protector = yes; then fi libc_extra_cppflags= -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker provides __ehdr_start" >&5 -$as_echo_n "checking whether the linker provides __ehdr_start... " >&6; } +# Some linkers on some architectures support __ehdr_start but with +# bugs. Make sure usage of it does not create relocations in the +# output (as the linker should resolve them all for us). +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker provides working __ehdr_start" >&5 +$as_echo_n "checking whether the linker provides working __ehdr_start... " >&6; } if ${libc_cv_ehdr_start+:} false; then : $as_echo_n "(cached) " >&6 else @@ -6980,12 +6983,20 @@ LIBS= cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -extern const char __ehdr_start __attribute__ ((visibility ("hidden"))); -const char *ehdr (void) { return &__ehdr_start; } +typedef struct { + char foo; + long val; +} Ehdr; +extern const Ehdr __ehdr_start __attribute__ ((visibility ("hidden"))); +long ehdr (void) { return __ehdr_start.val; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - libc_cv_ehdr_start=yes + if $READELF -r conftest | fgrep __ehdr_start >/dev/null; then + libc_cv_ehdr_start=broken + else + libc_cv_ehdr_start=yes + fi else libc_cv_ehdr_start=no fi @@ -6998,9 +7009,12 @@ LIBS="$old_LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_ehdr_start" >&5 $as_echo "$libc_cv_ehdr_start" >&6; } -if test $libc_cv_ehdr_start = yes; then +if test "$libc_cv_ehdr_start" = yes; then $as_echo "#define HAVE_EHDR_START 1" >>confdefs.h +elif test "$libc_cv_ehdr_start" = broken; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: linker is broken -- you should upgrade" >&5 +$as_echo "$as_me: WARNING: linker is broken -- you should upgrade" >&2;} fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_trap with no external dependencies" >&5 diff --git a/configure.ac b/configure.ac index e89faa0..2553399 100644 --- a/configure.ac +++ b/configure.ac @@ -1880,7 +1880,10 @@ if test $libc_cv_predef_stack_protector = yes; then fi libc_extra_cppflags= -AC_CACHE_CHECK([whether the linker provides __ehdr_start], +# Some linkers on some architectures support __ehdr_start but with +# bugs. Make sure usage of it does not create relocations in the +# output (as the linker should resolve them all for us). +AC_CACHE_CHECK([whether the linker provides working __ehdr_start], libc_cv_ehdr_start, [ old_CFLAGS="$CFLAGS" old_LDFLAGS="$LDFLAGS" @@ -1889,16 +1892,26 @@ CFLAGS="$CFLAGS -fPIC" LDFLAGS="$LDFLAGS -nostdlib -nostartfiles -shared" LIBS= AC_LINK_IFELSE([AC_LANG_SOURCE([ -extern const char __ehdr_start __attribute__ ((visibility ("hidden"))); -const char *ehdr (void) { return &__ehdr_start; } +typedef struct { + char foo; + long val; +} Ehdr; +extern const Ehdr __ehdr_start __attribute__ ((visibility ("hidden"))); +long ehdr (void) { return __ehdr_start.val; } ])], - [libc_cv_ehdr_start=yes], [libc_cv_ehdr_start=no]) + [if $READELF -r conftest | fgrep __ehdr_start >/dev/null; then + libc_cv_ehdr_start=broken + else + libc_cv_ehdr_start=yes + fi], [libc_cv_ehdr_start=no]) CFLAGS="$old_CFLAGS" LDFLAGS="$old_LDFLAGS" LIBS="$old_LIBS" ]) -if test $libc_cv_ehdr_start = yes; then +if test "$libc_cv_ehdr_start" = yes; then AC_DEFINE([HAVE_EHDR_START]) +elif test "$libc_cv_ehdr_start" = broken; then + AC_MSG_WARN([linker is broken -- you should upgrade]) fi AC_CACHE_CHECK(for __builtin_trap with no external dependencies,