[v2,3/3] configure: Allow LD to be LLD 13.0.0 or above [BZ #26558]

Message ID 20210805162601.1200851-4-maskray@google.com
State Committed
Headers
Series Allow LLD 13.0.0 and improve compatibility with gold and clang |

Checks

Context Check Description
dj/TryBot-apply_patch success Patch applied to master at the time it was sent
dj/TryBot-32bit success Build for i686

Commit Message

Fangrui Song Aug. 5, 2021, 4:26 p.m. UTC
  When using LLD (LLVM linker) as the linker, configure prints a confusing
message.

    *** These critical programs are missing or too old: GNU ld

LLD>=13.0.0 can build glibc --enable-static-pie. (8.0.0 needs one
workaround for -Wl,-defsym=_begin=0. 9.0.0 works with
--disable-static-pie).

With BZ #28153 (glibc bug exposed by testing with LLD) fixed,
`make check` only has 2 more failures with LLD than with GNU ld:
BZ #28154 (LLD follows the PowerPC port of GNU ld for ifunc by
placing IRELATIVE relocations in .rela.dyn).
The set of dynamic symbols is the same with GNU ld and LLD,
modulo unused SHN_ABS version node symbols.

For comparison, gold does not support --enable-static-pie
yet (--no-dynamic-linker is unsupported BZ #22221), yet
has 6 failures more than LLD. gold linked libc.so has
larger .dynsym differences with GNU ld and LLD
(ISTM non-default version symbols are changed to default versions
by a version script).

---

I identified the lack of support of

* version script on non-default version symbols
* copy relocations on non-default version symbols

in an earlier snapshot of LLD 13.0.0 and fixed them.
The functionality of the LLD linked libc.so and ld.so looks pretty good.
---
 configure    | 77 +++++++++++++++++++++++++++++++++++++++++++++++++---
 configure.ac | 20 ++++++++++----
 2 files changed, 88 insertions(+), 9 deletions(-)
  

Comments

H.J. Lu Aug. 5, 2021, 4:34 p.m. UTC | #1
On Thu, Aug 5, 2021 at 9:29 AM Fangrui Song via Libc-alpha
<libc-alpha@sourceware.org> wrote:
>
> When using LLD (LLVM linker) as the linker, configure prints a confusing
> message.
>
>     *** These critical programs are missing or too old: GNU ld
>
> LLD>=13.0.0 can build glibc --enable-static-pie. (8.0.0 needs one
> workaround for -Wl,-defsym=_begin=0. 9.0.0 works with
> --disable-static-pie).
>
> With BZ #28153 (glibc bug exposed by testing with LLD) fixed,
> `make check` only has 2 more failures with LLD than with GNU ld:
> BZ #28154 (LLD follows the PowerPC port of GNU ld for ifunc by
> placing IRELATIVE relocations in .rela.dyn).

This is an lld bug, similar to:

https://sourceware.org/bugzilla/show_bug.cgi?id=13302

Please fix it at least on x86.

> The set of dynamic symbols is the same with GNU ld and LLD,
> modulo unused SHN_ABS version node symbols.
>
> For comparison, gold does not support --enable-static-pie
> yet (--no-dynamic-linker is unsupported BZ #22221), yet
> has 6 failures more than LLD. gold linked libc.so has
> larger .dynsym differences with GNU ld and LLD
> (ISTM non-default version symbols are changed to default versions
> by a version script).
>
> ---
>
> I identified the lack of support of
>
> * version script on non-default version symbols
> * copy relocations on non-default version symbols
>
> in an earlier snapshot of LLD 13.0.0 and fixed them.
> The functionality of the LLD linked libc.so and ld.so looks pretty good.
> ---
>  configure    | 77 +++++++++++++++++++++++++++++++++++++++++++++++++---
>  configure.ac | 20 ++++++++++----
>  2 files changed, 88 insertions(+), 9 deletions(-)
>
> diff --git a/configure b/configure
> index 9b966196d4..050f1a29cf 100755
> --- a/configure
> +++ b/configure
> @@ -4664,9 +4664,10 @@ if test $ac_verc_fail = yes; then
>  fi
>
>
> -if test -n "`$LD --version | sed -n 's/^GNU \(gold\).*$/\1/p'`"; then
> +case $($LD --version) in
> +  "GNU gold"*)
>    # Accept gold 1.14 or higher
> -  for ac_prog in $LD
> +    for ac_prog in $LD
>  do
>    # Extract the first word of "$ac_prog", so it can be a program name with args.
>  set dummy $ac_prog; ac_word=$2
> @@ -4729,8 +4730,75 @@ if test $ac_verc_fail = yes; then
>    LD=: critic_missing="$critic_missing GNU gold"
>  fi
>
> +    ;;
> +  "LLD"*)
> +  # Accept LLD 13.0.0 or higher
> +    for ac_prog in $LD
> +do
> +  # Extract the first word of "$ac_prog", so it can be a program name with args.
> +set dummy $ac_prog; ac_word=$2
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
> +$as_echo_n "checking for $ac_word... " >&6; }
> +if ${ac_cv_prog_LD+:} false; then :
> +  $as_echo_n "(cached) " >&6
>  else
> -  for ac_prog in $LD
> +  if test -n "$LD"; then
> +  ac_cv_prog_LD="$LD" # Let the user override the test.
> +else
> +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
> +for as_dir in $PATH
> +do
> +  IFS=$as_save_IFS
> +  test -z "$as_dir" && as_dir=.
> +    for ac_exec_ext in '' $ac_executable_extensions; do
> +  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
> +    ac_cv_prog_LD="$ac_prog"
> +    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
> +    break 2
> +  fi
> +done
> +  done
> +IFS=$as_save_IFS
> +
> +fi
> +fi
> +LD=$ac_cv_prog_LD
> +if test -n "$LD"; then
> +  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
> +$as_echo "$LD" >&6; }
> +else
> +  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> +$as_echo "no" >&6; }
> +fi
> +
> +
> +  test -n "$LD" && break
> +done
> +
> +if test -z "$LD"; then
> +  ac_verc_fail=yes
> +else
> +  # Found it, now check the version.
> +  { $as_echo "$as_me:${as_lineno-$LINENO}: checking version of $LD" >&5
> +$as_echo_n "checking version of $LD... " >&6; }
> +  ac_prog_version=`$LD --version 2>&1 | sed -n 's/^.*LLD.* \([0-9][0-9]*\.[0-9.]*\).*$/\1/p'`
> +  case $ac_prog_version in
> +    '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
> +    1[3-9].*|[2-9][0-9].*)
> +       ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
> +    *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;;
> +
> +  esac
> +  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_prog_version" >&5
> +$as_echo "$ac_prog_version" >&6; }
> +fi
> +if test $ac_verc_fail = yes; then
> +  LD=: critic_missing="$critic_missing LLD"
> +fi
> +
> +    ;;
> +  *)
> +    for ac_prog in $LD
>  do
>    # Extract the first word of "$ac_prog", so it can be a program name with args.
>  set dummy $ac_prog; ac_word=$2
> @@ -4793,7 +4861,8 @@ if test $ac_verc_fail = yes; then
>    LD=: critic_missing="$critic_missing GNU ld"
>  fi
>
> -fi
> +    ;;
> +esac
>
>  # These programs are version sensitive.
>  for ac_prog in gnumake gmake make
> diff --git a/configure.ac b/configure.ac
> index 17a4c9a1ab..5632277f9c 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -995,18 +995,28 @@ AC_CHECK_PROG_VER(AS, $AS, --version,
>                   [2.1[0-9][0-9]*|2.2[5-9]*|2.[3-9][0-9]*|[3-9].*|[1-9][0-9]*],
>                   AS=: critic_missing="$critic_missing as")
>
> -if test -n "`$LD --version | sed -n 's/^GNU \(gold\).*$/\1/p'`"; then
> +case $($LD --version) in
> +  "GNU gold"*)
>    # Accept gold 1.14 or higher
> -  AC_CHECK_PROG_VER(LD, $LD, --version,
> +    AC_CHECK_PROG_VER(LD, $LD, --version,
>                     [GNU gold.* \([0-9][0-9]*\.[0-9.]*\)],
>                     [1.1[4-9]*|1.[2-9][0-9]*|1.1[0-9][0-9]*|[2-9].*|[1-9][0-9]*],
>                     LD=: critic_missing="$critic_missing GNU gold")
> -else
> -  AC_CHECK_PROG_VER(LD, $LD, --version,
> +    ;;
> +  "LLD"*)
> +  # Accept LLD 13.0.0 or higher
> +    AC_CHECK_PROG_VER(LD, $LD, --version,
> +                   [LLD.* \([0-9][0-9]*\.[0-9.]*\)],
> +                   [1[3-9].*|[2-9][0-9].*],
> +                   LD=: critic_missing="$critic_missing LLD")
> +    ;;
> +  *)
> +    AC_CHECK_PROG_VER(LD, $LD, --version,
>                     [GNU ld.* \([0-9][0-9]*\.[0-9.]*\)],
>                     [2.1[0-9][0-9]*|2.2[5-9]*|2.[3-9][0-9]*|[3-9].*|[1-9][0-9]*],
>                     LD=: critic_missing="$critic_missing GNU ld")
> -fi
> +    ;;
> +esac
>
>  # These programs are version sensitive.
>  AC_CHECK_PROG_VER(MAKE, gnumake gmake make, --version,
> --
> 2.32.0.605.g8dce9f2422-goog
>
  
Fangrui Song Aug. 5, 2021, 4:43 p.m. UTC | #2
On Thu, Aug 5, 2021 at 9:34 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Thu, Aug 5, 2021 at 9:29 AM Fangrui Song via Libc-alpha
> <libc-alpha@sourceware.org> wrote:
> >
> > When using LLD (LLVM linker) as the linker, configure prints a confusing
> > message.
> >
> >     *** These critical programs are missing or too old: GNU ld
> >
> > LLD>=13.0.0 can build glibc --enable-static-pie. (8.0.0 needs one
> > workaround for -Wl,-defsym=_begin=0. 9.0.0 works with
> > --disable-static-pie).
> >
> > With BZ #28153 (glibc bug exposed by testing with LLD) fixed,
> > `make check` only has 2 more failures with LLD than with GNU ld:
> > BZ #28154 (LLD follows the PowerPC port of GNU ld for ifunc by
> > placing IRELATIVE relocations in .rela.dyn).
>
> This is an lld bug, similar to:
>
> https://sourceware.org/bugzilla/show_bug.cgi?id=13302
>
> Please fix it at least on x86.

I am afraid that I disagree. The PowerPC port of GNU ld does the right
thing and LLD follows suit.
R_*_IRELATIVE relocations should be eagerly resolved, so they belong
to .rela.dyn instead of .rela.plt.

The objection argument
https://sourceware.org/bugzilla/show_bug.cgi?id=28154#c3 is kinda
weak:

> This requires both linker and ld.so changes.  The PR ld/13302 linker change doesn't require ld.so change.

Working around the glibc ld.so issue on GNU ld side was probably
simpler, but that does not justify the GNU ld change.

I mentioned at #c2 about the proper way on the glibc side.

But our conflict here may be moot because in practice ifunc should not
have such PLT calls, they would be unreliable on other architectures
anyway.

> > The set of dynamic symbols is the same with GNU ld and LLD,
> > modulo unused SHN_ABS version node symbols.
> >
> > For comparison, gold does not support --enable-static-pie
> > yet (--no-dynamic-linker is unsupported BZ #22221), yet
> > has 6 failures more than LLD. gold linked libc.so has
> > larger .dynsym differences with GNU ld and LLD
> > (ISTM non-default version symbols are changed to default versions
> > by a version script).
> >
> > ---
> >
> > I identified the lack of support of
> >
> > * version script on non-default version symbols
> > * copy relocations on non-default version symbols
> >
> > in an earlier snapshot of LLD 13.0.0 and fixed them.
> > The functionality of the LLD linked libc.so and ld.so looks pretty good.
> > ---
> >  configure    | 77 +++++++++++++++++++++++++++++++++++++++++++++++++---
> >  configure.ac | 20 ++++++++++----
> >  2 files changed, 88 insertions(+), 9 deletions(-)
> >
> > diff --git a/configure b/configure
> > index 9b966196d4..050f1a29cf 100755
> > --- a/configure
> > +++ b/configure
> > @@ -4664,9 +4664,10 @@ if test $ac_verc_fail = yes; then
> >  fi
> >
> >
> > -if test -n "`$LD --version | sed -n 's/^GNU \(gold\).*$/\1/p'`"; then
> > +case $($LD --version) in
> > +  "GNU gold"*)
> >    # Accept gold 1.14 or higher
> > -  for ac_prog in $LD
> > +    for ac_prog in $LD
> >  do
> >    # Extract the first word of "$ac_prog", so it can be a program name with args.
> >  set dummy $ac_prog; ac_word=$2
> > @@ -4729,8 +4730,75 @@ if test $ac_verc_fail = yes; then
> >    LD=: critic_missing="$critic_missing GNU gold"
> >  fi
> >
> > +    ;;
> > +  "LLD"*)
> > +  # Accept LLD 13.0.0 or higher
> > +    for ac_prog in $LD
> > +do
> > +  # Extract the first word of "$ac_prog", so it can be a program name with args.
> > +set dummy $ac_prog; ac_word=$2
> > +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
> > +$as_echo_n "checking for $ac_word... " >&6; }
> > +if ${ac_cv_prog_LD+:} false; then :
> > +  $as_echo_n "(cached) " >&6
> >  else
> > -  for ac_prog in $LD
> > +  if test -n "$LD"; then
> > +  ac_cv_prog_LD="$LD" # Let the user override the test.
> > +else
> > +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
> > +for as_dir in $PATH
> > +do
> > +  IFS=$as_save_IFS
> > +  test -z "$as_dir" && as_dir=.
> > +    for ac_exec_ext in '' $ac_executable_extensions; do
> > +  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
> > +    ac_cv_prog_LD="$ac_prog"
> > +    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
> > +    break 2
> > +  fi
> > +done
> > +  done
> > +IFS=$as_save_IFS
> > +
> > +fi
> > +fi
> > +LD=$ac_cv_prog_LD
> > +if test -n "$LD"; then
> > +  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
> > +$as_echo "$LD" >&6; }
> > +else
> > +  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> > +$as_echo "no" >&6; }
> > +fi
> > +
> > +
> > +  test -n "$LD" && break
> > +done
> > +
> > +if test -z "$LD"; then
> > +  ac_verc_fail=yes
> > +else
> > +  # Found it, now check the version.
> > +  { $as_echo "$as_me:${as_lineno-$LINENO}: checking version of $LD" >&5
> > +$as_echo_n "checking version of $LD... " >&6; }
> > +  ac_prog_version=`$LD --version 2>&1 | sed -n 's/^.*LLD.* \([0-9][0-9]*\.[0-9.]*\).*$/\1/p'`
> > +  case $ac_prog_version in
> > +    '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
> > +    1[3-9].*|[2-9][0-9].*)
> > +       ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
> > +    *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;;
> > +
> > +  esac
> > +  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_prog_version" >&5
> > +$as_echo "$ac_prog_version" >&6; }
> > +fi
> > +if test $ac_verc_fail = yes; then
> > +  LD=: critic_missing="$critic_missing LLD"
> > +fi
> > +
> > +    ;;
> > +  *)
> > +    for ac_prog in $LD
> >  do
> >    # Extract the first word of "$ac_prog", so it can be a program name with args.
> >  set dummy $ac_prog; ac_word=$2
> > @@ -4793,7 +4861,8 @@ if test $ac_verc_fail = yes; then
> >    LD=: critic_missing="$critic_missing GNU ld"
> >  fi
> >
> > -fi
> > +    ;;
> > +esac
> >
> >  # These programs are version sensitive.
> >  for ac_prog in gnumake gmake make
> > diff --git a/configure.ac b/configure.ac
> > index 17a4c9a1ab..5632277f9c 100644
> > --- a/configure.ac
> > +++ b/configure.ac
> > @@ -995,18 +995,28 @@ AC_CHECK_PROG_VER(AS, $AS, --version,
> >                   [2.1[0-9][0-9]*|2.2[5-9]*|2.[3-9][0-9]*|[3-9].*|[1-9][0-9]*],
> >                   AS=: critic_missing="$critic_missing as")
> >
> > -if test -n "`$LD --version | sed -n 's/^GNU \(gold\).*$/\1/p'`"; then
> > +case $($LD --version) in
> > +  "GNU gold"*)
> >    # Accept gold 1.14 or higher
> > -  AC_CHECK_PROG_VER(LD, $LD, --version,
> > +    AC_CHECK_PROG_VER(LD, $LD, --version,
> >                     [GNU gold.* \([0-9][0-9]*\.[0-9.]*\)],
> >                     [1.1[4-9]*|1.[2-9][0-9]*|1.1[0-9][0-9]*|[2-9].*|[1-9][0-9]*],
> >                     LD=: critic_missing="$critic_missing GNU gold")
> > -else
> > -  AC_CHECK_PROG_VER(LD, $LD, --version,
> > +    ;;
> > +  "LLD"*)
> > +  # Accept LLD 13.0.0 or higher
> > +    AC_CHECK_PROG_VER(LD, $LD, --version,
> > +                   [LLD.* \([0-9][0-9]*\.[0-9.]*\)],
> > +                   [1[3-9].*|[2-9][0-9].*],
> > +                   LD=: critic_missing="$critic_missing LLD")
> > +    ;;
> > +  *)
> > +    AC_CHECK_PROG_VER(LD, $LD, --version,
> >                     [GNU ld.* \([0-9][0-9]*\.[0-9.]*\)],
> >                     [2.1[0-9][0-9]*|2.2[5-9]*|2.[3-9][0-9]*|[3-9].*|[1-9][0-9]*],
> >                     LD=: critic_missing="$critic_missing GNU ld")
> > -fi
> > +    ;;
> > +esac
> >
> >  # These programs are version sensitive.
> >  AC_CHECK_PROG_VER(MAKE, gnumake gmake make, --version,
> > --
> > 2.32.0.605.g8dce9f2422-goog
  
H.J. Lu Aug. 5, 2021, 5:04 p.m. UTC | #3
On Thu, Aug 5, 2021 at 9:43 AM Fāng-ruì Sòng <maskray@google.com> wrote:
>
> On Thu, Aug 5, 2021 at 9:34 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Thu, Aug 5, 2021 at 9:29 AM Fangrui Song via Libc-alpha
> > <libc-alpha@sourceware.org> wrote:
> > >
> > > When using LLD (LLVM linker) as the linker, configure prints a confusing
> > > message.
> > >
> > >     *** These critical programs are missing or too old: GNU ld
> > >
> > > LLD>=13.0.0 can build glibc --enable-static-pie. (8.0.0 needs one
> > > workaround for -Wl,-defsym=_begin=0. 9.0.0 works with
> > > --disable-static-pie).
> > >
> > > With BZ #28153 (glibc bug exposed by testing with LLD) fixed,
> > > `make check` only has 2 more failures with LLD than with GNU ld:
> > > BZ #28154 (LLD follows the PowerPC port of GNU ld for ifunc by
> > > placing IRELATIVE relocations in .rela.dyn).
> >
> > This is an lld bug, similar to:
> >
> > https://sourceware.org/bugzilla/show_bug.cgi?id=13302
> >
> > Please fix it at least on x86.
>
> I am afraid that I disagree. The PowerPC port of GNU ld does the right

This is just one opinion and it doesn't make it "the right thing".

> thing and LLD follows suit.
> R_*_IRELATIVE relocations should be eagerly resolved, so they belong
> to .rela.dyn instead of .rela.plt.

Ulrich and I designed/implemented IFUNC on x86 and for x86.  I consider
x86 implementation of IFUC as the gold standard.

> The objection argument
> https://sourceware.org/bugzilla/show_bug.cgi?id=28154#c3 is kinda
> weak:
>
> > This requires both linker and ld.so changes.  The PR ld/13302 linker change doesn't require ld.so change.
>
> Working around the glibc ld.so issue on GNU ld side was probably
> simpler, but that does not justify the GNU ld change.
>
> I mentioned at #c2 about the proper way on the glibc side.
>
> But our conflict here may be moot because in practice ifunc should not
> have such PLT calls, they would be unreliable on other architectures
> anyway.
>
> > > The set of dynamic symbols is the same with GNU ld and LLD,
> > > modulo unused SHN_ABS version node symbols.
> > >
> > > For comparison, gold does not support --enable-static-pie
> > > yet (--no-dynamic-linker is unsupported BZ #22221), yet
> > > has 6 failures more than LLD. gold linked libc.so has
> > > larger .dynsym differences with GNU ld and LLD
> > > (ISTM non-default version symbols are changed to default versions
> > > by a version script).
> > >
> > > ---
> > >
> > > I identified the lack of support of
> > >
> > > * version script on non-default version symbols
> > > * copy relocations on non-default version symbols
> > >
> > > in an earlier snapshot of LLD 13.0.0 and fixed them.
> > > The functionality of the LLD linked libc.so and ld.so looks pretty good.
> > > ---
> > >  configure    | 77 +++++++++++++++++++++++++++++++++++++++++++++++++---
> > >  configure.ac | 20 ++++++++++----
> > >  2 files changed, 88 insertions(+), 9 deletions(-)
> > >
> > > diff --git a/configure b/configure
> > > index 9b966196d4..050f1a29cf 100755
> > > --- a/configure
> > > +++ b/configure
> > > @@ -4664,9 +4664,10 @@ if test $ac_verc_fail = yes; then
> > >  fi
> > >
> > >
> > > -if test -n "`$LD --version | sed -n 's/^GNU \(gold\).*$/\1/p'`"; then
> > > +case $($LD --version) in
> > > +  "GNU gold"*)
> > >    # Accept gold 1.14 or higher
> > > -  for ac_prog in $LD
> > > +    for ac_prog in $LD
> > >  do
> > >    # Extract the first word of "$ac_prog", so it can be a program name with args.
> > >  set dummy $ac_prog; ac_word=$2
> > > @@ -4729,8 +4730,75 @@ if test $ac_verc_fail = yes; then
> > >    LD=: critic_missing="$critic_missing GNU gold"
> > >  fi
> > >
> > > +    ;;
> > > +  "LLD"*)
> > > +  # Accept LLD 13.0.0 or higher
> > > +    for ac_prog in $LD
> > > +do
> > > +  # Extract the first word of "$ac_prog", so it can be a program name with args.
> > > +set dummy $ac_prog; ac_word=$2
> > > +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
> > > +$as_echo_n "checking for $ac_word... " >&6; }
> > > +if ${ac_cv_prog_LD+:} false; then :
> > > +  $as_echo_n "(cached) " >&6
> > >  else
> > > -  for ac_prog in $LD
> > > +  if test -n "$LD"; then
> > > +  ac_cv_prog_LD="$LD" # Let the user override the test.
> > > +else
> > > +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
> > > +for as_dir in $PATH
> > > +do
> > > +  IFS=$as_save_IFS
> > > +  test -z "$as_dir" && as_dir=.
> > > +    for ac_exec_ext in '' $ac_executable_extensions; do
> > > +  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
> > > +    ac_cv_prog_LD="$ac_prog"
> > > +    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
> > > +    break 2
> > > +  fi
> > > +done
> > > +  done
> > > +IFS=$as_save_IFS
> > > +
> > > +fi
> > > +fi
> > > +LD=$ac_cv_prog_LD
> > > +if test -n "$LD"; then
> > > +  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
> > > +$as_echo "$LD" >&6; }
> > > +else
> > > +  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> > > +$as_echo "no" >&6; }
> > > +fi
> > > +
> > > +
> > > +  test -n "$LD" && break
> > > +done
> > > +
> > > +if test -z "$LD"; then
> > > +  ac_verc_fail=yes
> > > +else
> > > +  # Found it, now check the version.
> > > +  { $as_echo "$as_me:${as_lineno-$LINENO}: checking version of $LD" >&5
> > > +$as_echo_n "checking version of $LD... " >&6; }
> > > +  ac_prog_version=`$LD --version 2>&1 | sed -n 's/^.*LLD.* \([0-9][0-9]*\.[0-9.]*\).*$/\1/p'`
> > > +  case $ac_prog_version in
> > > +    '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
> > > +    1[3-9].*|[2-9][0-9].*)
> > > +       ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
> > > +    *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;;
> > > +
> > > +  esac
> > > +  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_prog_version" >&5
> > > +$as_echo "$ac_prog_version" >&6; }
> > > +fi
> > > +if test $ac_verc_fail = yes; then
> > > +  LD=: critic_missing="$critic_missing LLD"
> > > +fi
> > > +
> > > +    ;;
> > > +  *)
> > > +    for ac_prog in $LD
> > >  do
> > >    # Extract the first word of "$ac_prog", so it can be a program name with args.
> > >  set dummy $ac_prog; ac_word=$2
> > > @@ -4793,7 +4861,8 @@ if test $ac_verc_fail = yes; then
> > >    LD=: critic_missing="$critic_missing GNU ld"
> > >  fi
> > >
> > > -fi
> > > +    ;;
> > > +esac
> > >
> > >  # These programs are version sensitive.
> > >  for ac_prog in gnumake gmake make
> > > diff --git a/configure.ac b/configure.ac
> > > index 17a4c9a1ab..5632277f9c 100644
> > > --- a/configure.ac
> > > +++ b/configure.ac
> > > @@ -995,18 +995,28 @@ AC_CHECK_PROG_VER(AS, $AS, --version,
> > >                   [2.1[0-9][0-9]*|2.2[5-9]*|2.[3-9][0-9]*|[3-9].*|[1-9][0-9]*],
> > >                   AS=: critic_missing="$critic_missing as")
> > >
> > > -if test -n "`$LD --version | sed -n 's/^GNU \(gold\).*$/\1/p'`"; then
> > > +case $($LD --version) in
> > > +  "GNU gold"*)
> > >    # Accept gold 1.14 or higher
> > > -  AC_CHECK_PROG_VER(LD, $LD, --version,
> > > +    AC_CHECK_PROG_VER(LD, $LD, --version,
> > >                     [GNU gold.* \([0-9][0-9]*\.[0-9.]*\)],
> > >                     [1.1[4-9]*|1.[2-9][0-9]*|1.1[0-9][0-9]*|[2-9].*|[1-9][0-9]*],
> > >                     LD=: critic_missing="$critic_missing GNU gold")
> > > -else
> > > -  AC_CHECK_PROG_VER(LD, $LD, --version,
> > > +    ;;
> > > +  "LLD"*)
> > > +  # Accept LLD 13.0.0 or higher
> > > +    AC_CHECK_PROG_VER(LD, $LD, --version,
> > > +                   [LLD.* \([0-9][0-9]*\.[0-9.]*\)],
> > > +                   [1[3-9].*|[2-9][0-9].*],
> > > +                   LD=: critic_missing="$critic_missing LLD")
> > > +    ;;
> > > +  *)
> > > +    AC_CHECK_PROG_VER(LD, $LD, --version,
> > >                     [GNU ld.* \([0-9][0-9]*\.[0-9.]*\)],
> > >                     [2.1[0-9][0-9]*|2.2[5-9]*|2.[3-9][0-9]*|[3-9].*|[1-9][0-9]*],
> > >                     LD=: critic_missing="$critic_missing GNU ld")
> > > -fi
> > > +    ;;
> > > +esac
> > >
> > >  # These programs are version sensitive.
> > >  AC_CHECK_PROG_VER(MAKE, gnumake gmake make, --version,
> > > --
> > > 2.32.0.605.g8dce9f2422-goog



--
H.J.
  
Fangrui Song Aug. 7, 2021, 12:47 a.m. UTC | #4
On 2021-08-05, H.J. Lu wrote:
>On Thu, Aug 5, 2021 at 9:43 AM Fāng-ruì Sòng <maskray@google.com> wrote:
>>
>> On Thu, Aug 5, 2021 at 9:34 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>> >
>> > On Thu, Aug 5, 2021 at 9:29 AM Fangrui Song via Libc-alpha
>> > <libc-alpha@sourceware.org> wrote:
>> > >
>> > > When using LLD (LLVM linker) as the linker, configure prints a confusing
>> > > message.
>> > >
>> > >     *** These critical programs are missing or too old: GNU ld
>> > >
>> > > LLD>=13.0.0 can build glibc --enable-static-pie. (8.0.0 needs one
>> > > workaround for -Wl,-defsym=_begin=0. 9.0.0 works with
>> > > --disable-static-pie).
>> > >
>> > > With BZ #28153 (glibc bug exposed by testing with LLD) fixed,
>> > > `make check` only has 2 more failures with LLD than with GNU ld:
>> > > BZ #28154 (LLD follows the PowerPC port of GNU ld for ifunc by
>> > > placing IRELATIVE relocations in .rela.dyn).
>> >
>> > This is an lld bug, similar to:
>> >
>> > https://sourceware.org/bugzilla/show_bug.cgi?id=13302
>> >
>> > Please fix it at least on x86.
>>
>> I am afraid that I disagree. The PowerPC port of GNU ld does the right
>
>This is just one opinion and it doesn't make it "the right thing".
>
>> thing and LLD follows suit.
>> R_*_IRELATIVE relocations should be eagerly resolved, so they belong
>> to .rela.dyn instead of .rela.plt.
>
>Ulrich and I designed/implemented IFUNC on x86 and for x86.  I consider
>x86 implementation of IFUC as the gold standard.

kib from FreeBSD said

"FreeBSD rtld does the initial pass over the plt relocations and handles
R_X86_64_JMP_SLOT only, If there are any R_X86_64_IRELATIVE relocks, we
mark the object as having such relocations. Then, we do the ireloc
processing, using the depth-first descend. We handle all IRELOCs for
dependent objects before doing it for dependee. There, we iterate over
all plt relocs to select IRELOCs."

I pondered at this comment

/*
  * The handling of R_MACHINE_IRELATIVE relocations and jumpslots
  * referencing STT_GNU_IFUNC symbols is postponed till the other
  * relocations are done.  The indirect functions specified as
  * ifunc are allowed to call other symbols, so we need to have
  * objects relocated before asking for resolution from indirects.
  *
  * The R_MACHINE_IRELATIVE slots are resolved in greedy fashion,
  * instead of the usual lazy handling of PLT slots.  It is
  * consistent with how GNU does it.
  */

and re-read https://sourceware.org/glibc/wiki/GNU_IFUNC

"This may work on x86_64 where the R_*_IRELATIVE relocations happen in
DT_JMPREL after the DT_REL* relocations, but that is no guarantee that it will
work on AArch64, PPC64, or other architectures that are slightly different.
Such fundamental limitations may be lifted at a future point."

I think adopting the FreeBSD approach can make IRELATIVE more robust, even for
x86. IRELATIVE is still eager resolved, just postponed after other relocations.
Fixing this property in glibc will improve rubustness/flexibility of ifunc
resolvers and freeing linkers the responsibility to order IRELATIVE in a
particular position.

Pioneering on one feature gives the designer respect, yet the designer can only
earn authority by demonstrating the consideration of all sort of implication.

>> The objection argument
>> https://sourceware.org/bugzilla/show_bug.cgi?id=28154#c3 is kinda
>> weak:
>>
>> > This requires both linker and ld.so changes.  The PR ld/13302 linker change doesn't require ld.so change.
>>
>> Working around the glibc ld.so issue on GNU ld side was probably
>> simpler, but that does not justify the GNU ld change.
>>
>> I mentioned at #c2 about the proper way on the glibc side.
>>
>> But our conflict here may be moot because in practice ifunc should not
>> have such PLT calls, they would be unreliable on other architectures
>> anyway.
>>
>> > > The set of dynamic symbols is the same with GNU ld and LLD,
>> > > modulo unused SHN_ABS version node symbols.
>> > >
>> > > For comparison, gold does not support --enable-static-pie
>> > > yet (--no-dynamic-linker is unsupported BZ #22221), yet
>> > > has 6 failures more than LLD. gold linked libc.so has
>> > > larger .dynsym differences with GNU ld and LLD
>> > > (ISTM non-default version symbols are changed to default versions
>> > > by a version script).
>> > >
>> > > ---
>> > >
>> > > I identified the lack of support of
>> > >
>> > > * version script on non-default version symbols
>> > > * copy relocations on non-default version symbols
>> > >
>> > > in an earlier snapshot of LLD 13.0.0 and fixed them.
>> > > The functionality of the LLD linked libc.so and ld.so looks pretty good.
>> > > ---
>> > >  configure    | 77 +++++++++++++++++++++++++++++++++++++++++++++++++---
>> > >  configure.ac | 20 ++++++++++----
>> > >  2 files changed, 88 insertions(+), 9 deletions(-)
>> > >
>> > > diff --git a/configure b/configure
>> > > index 9b966196d4..050f1a29cf 100755
>> > > --- a/configure
>> > > +++ b/configure
>> > > @@ -4664,9 +4664,10 @@ if test $ac_verc_fail = yes; then
>> > >  fi
>> > >
>> > >
>> > > -if test -n "`$LD --version | sed -n 's/^GNU \(gold\).*$/\1/p'`"; then
>> > > +case $($LD --version) in
>> > > +  "GNU gold"*)
>> > >    # Accept gold 1.14 or higher
>> > > -  for ac_prog in $LD
>> > > +    for ac_prog in $LD
>> > >  do
>> > >    # Extract the first word of "$ac_prog", so it can be a program name with args.
>> > >  set dummy $ac_prog; ac_word=$2
>> > > @@ -4729,8 +4730,75 @@ if test $ac_verc_fail = yes; then
>> > >    LD=: critic_missing="$critic_missing GNU gold"
>> > >  fi
>> > >
>> > > +    ;;
>> > > +  "LLD"*)
>> > > +  # Accept LLD 13.0.0 or higher
>> > > +    for ac_prog in $LD
>> > > +do
>> > > +  # Extract the first word of "$ac_prog", so it can be a program name with args.
>> > > +set dummy $ac_prog; ac_word=$2
>> > > +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
>> > > +$as_echo_n "checking for $ac_word... " >&6; }
>> > > +if ${ac_cv_prog_LD+:} false; then :
>> > > +  $as_echo_n "(cached) " >&6
>> > >  else
>> > > -  for ac_prog in $LD
>> > > +  if test -n "$LD"; then
>> > > +  ac_cv_prog_LD="$LD" # Let the user override the test.
>> > > +else
>> > > +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
>> > > +for as_dir in $PATH
>> > > +do
>> > > +  IFS=$as_save_IFS
>> > > +  test -z "$as_dir" && as_dir=.
>> > > +    for ac_exec_ext in '' $ac_executable_extensions; do
>> > > +  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
>> > > +    ac_cv_prog_LD="$ac_prog"
>> > > +    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
>> > > +    break 2
>> > > +  fi
>> > > +done
>> > > +  done
>> > > +IFS=$as_save_IFS
>> > > +
>> > > +fi
>> > > +fi
>> > > +LD=$ac_cv_prog_LD
>> > > +if test -n "$LD"; then
>> > > +  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
>> > > +$as_echo "$LD" >&6; }
>> > > +else
>> > > +  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
>> > > +$as_echo "no" >&6; }
>> > > +fi
>> > > +
>> > > +
>> > > +  test -n "$LD" && break
>> > > +done
>> > > +
>> > > +if test -z "$LD"; then
>> > > +  ac_verc_fail=yes
>> > > +else
>> > > +  # Found it, now check the version.
>> > > +  { $as_echo "$as_me:${as_lineno-$LINENO}: checking version of $LD" >&5
>> > > +$as_echo_n "checking version of $LD... " >&6; }
>> > > +  ac_prog_version=`$LD --version 2>&1 | sed -n 's/^.*LLD.* \([0-9][0-9]*\.[0-9.]*\).*$/\1/p'`
>> > > +  case $ac_prog_version in
>> > > +    '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
>> > > +    1[3-9].*|[2-9][0-9].*)
>> > > +       ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
>> > > +    *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;;
>> > > +
>> > > +  esac
>> > > +  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_prog_version" >&5
>> > > +$as_echo "$ac_prog_version" >&6; }
>> > > +fi
>> > > +if test $ac_verc_fail = yes; then
>> > > +  LD=: critic_missing="$critic_missing LLD"
>> > > +fi
>> > > +
>> > > +    ;;
>> > > +  *)
>> > > +    for ac_prog in $LD
>> > >  do
>> > >    # Extract the first word of "$ac_prog", so it can be a program name with args.
>> > >  set dummy $ac_prog; ac_word=$2
>> > > @@ -4793,7 +4861,8 @@ if test $ac_verc_fail = yes; then
>> > >    LD=: critic_missing="$critic_missing GNU ld"
>> > >  fi
>> > >
>> > > -fi
>> > > +    ;;
>> > > +esac
>> > >
>> > >  # These programs are version sensitive.
>> > >  for ac_prog in gnumake gmake make
>> > > diff --git a/configure.ac b/configure.ac
>> > > index 17a4c9a1ab..5632277f9c 100644
>> > > --- a/configure.ac
>> > > +++ b/configure.ac
>> > > @@ -995,18 +995,28 @@ AC_CHECK_PROG_VER(AS, $AS, --version,
>> > >                   [2.1[0-9][0-9]*|2.2[5-9]*|2.[3-9][0-9]*|[3-9].*|[1-9][0-9]*],
>> > >                   AS=: critic_missing="$critic_missing as")
>> > >
>> > > -if test -n "`$LD --version | sed -n 's/^GNU \(gold\).*$/\1/p'`"; then
>> > > +case $($LD --version) in
>> > > +  "GNU gold"*)
>> > >    # Accept gold 1.14 or higher
>> > > -  AC_CHECK_PROG_VER(LD, $LD, --version,
>> > > +    AC_CHECK_PROG_VER(LD, $LD, --version,
>> > >                     [GNU gold.* \([0-9][0-9]*\.[0-9.]*\)],
>> > >                     [1.1[4-9]*|1.[2-9][0-9]*|1.1[0-9][0-9]*|[2-9].*|[1-9][0-9]*],
>> > >                     LD=: critic_missing="$critic_missing GNU gold")
>> > > -else
>> > > -  AC_CHECK_PROG_VER(LD, $LD, --version,
>> > > +    ;;
>> > > +  "LLD"*)
>> > > +  # Accept LLD 13.0.0 or higher
>> > > +    AC_CHECK_PROG_VER(LD, $LD, --version,
>> > > +                   [LLD.* \([0-9][0-9]*\.[0-9.]*\)],
>> > > +                   [1[3-9].*|[2-9][0-9].*],
>> > > +                   LD=: critic_missing="$critic_missing LLD")
>> > > +    ;;
>> > > +  *)
>> > > +    AC_CHECK_PROG_VER(LD, $LD, --version,
>> > >                     [GNU ld.* \([0-9][0-9]*\.[0-9.]*\)],
>> > >                     [2.1[0-9][0-9]*|2.2[5-9]*|2.[3-9][0-9]*|[3-9].*|[1-9][0-9]*],
>> > >                     LD=: critic_missing="$critic_missing GNU ld")
>> > > -fi
>> > > +    ;;
>> > > +esac
>> > >
>> > >  # These programs are version sensitive.
>> > >  AC_CHECK_PROG_VER(MAKE, gnumake gmake make, --version,
>> > > --
>> > > 2.32.0.605.g8dce9f2422-goog
>
>
>
>--
>H.J.
  
H.J. Lu Aug. 7, 2021, 1:15 p.m. UTC | #5
On Fri, Aug 6, 2021 at 5:48 PM Fāng-ruì Sòng <maskray@google.com> wrote:
>
> On 2021-08-05, H.J. Lu wrote:
> >On Thu, Aug 5, 2021 at 9:43 AM Fāng-ruì Sòng <maskray@google.com> wrote:
> >>
> >> On Thu, Aug 5, 2021 at 9:34 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >> >
> >> > On Thu, Aug 5, 2021 at 9:29 AM Fangrui Song via Libc-alpha
> >> > <libc-alpha@sourceware.org> wrote:
> >> > >
> >> > > When using LLD (LLVM linker) as the linker, configure prints a confusing
> >> > > message.
> >> > >
> >> > >     *** These critical programs are missing or too old: GNU ld
> >> > >
> >> > > LLD>=13.0.0 can build glibc --enable-static-pie. (8.0.0 needs one
> >> > > workaround for -Wl,-defsym=_begin=0. 9.0.0 works with
> >> > > --disable-static-pie).
> >> > >
> >> > > With BZ #28153 (glibc bug exposed by testing with LLD) fixed,
> >> > > `make check` only has 2 more failures with LLD than with GNU ld:
> >> > > BZ #28154 (LLD follows the PowerPC port of GNU ld for ifunc by
> >> > > placing IRELATIVE relocations in .rela.dyn).
> >> >
> >> > This is an lld bug, similar to:
> >> >
> >> > https://sourceware.org/bugzilla/show_bug.cgi?id=13302
> >> >
> >> > Please fix it at least on x86.
> >>
> >> I am afraid that I disagree. The PowerPC port of GNU ld does the right
> >
> >This is just one opinion and it doesn't make it "the right thing".
> >
> >> thing and LLD follows suit.
> >> R_*_IRELATIVE relocations should be eagerly resolved, so they belong
> >> to .rela.dyn instead of .rela.plt.
> >
> >Ulrich and I designed/implemented IFUNC on x86 and for x86.  I consider
> >x86 implementation of IFUC as the gold standard.
>
> kib from FreeBSD said
>
> "FreeBSD rtld does the initial pass over the plt relocations and handles
> R_X86_64_JMP_SLOT only, If there are any R_X86_64_IRELATIVE relocks, we
> mark the object as having such relocations. Then, we do the ireloc
> processing, using the depth-first descend. We handle all IRELOCs for
> dependent objects before doing it for dependee. There, we iterate over
> all plt relocs to select IRELOCs."
>
> I pondered at this comment
>
> /*
>   * The handling of R_MACHINE_IRELATIVE relocations and jumpslots
>   * referencing STT_GNU_IFUNC symbols is postponed till the other
>   * relocations are done.  The indirect functions specified as
>   * ifunc are allowed to call other symbols, so we need to have
>   * objects relocated before asking for resolution from indirects.
>   *
>   * The R_MACHINE_IRELATIVE slots are resolved in greedy fashion,
>   * instead of the usual lazy handling of PLT slots.  It is
>   * consistent with how GNU does it.
>   */
>
> and re-read https://sourceware.org/glibc/wiki/GNU_IFUNC
>
> "This may work on x86_64 where the R_*_IRELATIVE relocations happen in
> DT_JMPREL after the DT_REL* relocations, but that is no guarantee that it will
> work on AArch64, PPC64, or other architectures that are slightly different.
> Such fundamental limitations may be lifted at a future point."
>
> I think adopting the FreeBSD approach can make IRELATIVE more robust, even for
> x86. IRELATIVE is still eager resolved, just postponed after other relocations.
> Fixing this property in glibc will improve rubustness/flexibility of ifunc
> resolvers and freeing linkers the responsibility to order IRELATIVE in a
> particular position.
>
> Pioneering on one feature gives the designer respect, yet the designer can only
> earn authority by demonstrating the consideration of all sort of implication.
>

On Linux/x86, lld is incompatible with ld.so on this particular IFUNC feature.
We have 3 choices:

1. Ignore it.  But it means that if lld is used to build glibc, we don't know if
this feature works or not.
2. Change glibc to make it compatible with lld.
3. Change lld to make it compatible with glibc.

The FreeBSD scheme is not wrong.  But it is a workaround in glibc
for a linker bug unless it also fixes other IFUNC issues on Linux/x86.
  
Fangrui Song Aug. 8, 2021, 4:17 a.m. UTC | #6
On 2021-08-07, H.J. Lu wrote:
>On Fri, Aug 6, 2021 at 5:48 PM Fāng-ruì Sòng <maskray@google.com> wrote:
>>
>> On 2021-08-05, H.J. Lu wrote:
>> >On Thu, Aug 5, 2021 at 9:43 AM Fāng-ruì Sòng <maskray@google.com> wrote:
>> >>
>> >> On Thu, Aug 5, 2021 at 9:34 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>> >> >
>> >> > On Thu, Aug 5, 2021 at 9:29 AM Fangrui Song via Libc-alpha
>> >> > <libc-alpha@sourceware.org> wrote:
>> >> > >
>> >> > > When using LLD (LLVM linker) as the linker, configure prints a confusing
>> >> > > message.
>> >> > >
>> >> > >     *** These critical programs are missing or too old: GNU ld
>> >> > >
>> >> > > LLD>=13.0.0 can build glibc --enable-static-pie. (8.0.0 needs one
>> >> > > workaround for -Wl,-defsym=_begin=0. 9.0.0 works with
>> >> > > --disable-static-pie).
>> >> > >
>> >> > > With BZ #28153 (glibc bug exposed by testing with LLD) fixed,
>> >> > > `make check` only has 2 more failures with LLD than with GNU ld:
>> >> > > BZ #28154 (LLD follows the PowerPC port of GNU ld for ifunc by
>> >> > > placing IRELATIVE relocations in .rela.dyn).
>> >> >
>> >> > This is an lld bug, similar to:
>> >> >
>> >> > https://sourceware.org/bugzilla/show_bug.cgi?id=13302
>> >> >
>> >> > Please fix it at least on x86.
>> >>
>> >> I am afraid that I disagree. The PowerPC port of GNU ld does the right
>> >
>> >This is just one opinion and it doesn't make it "the right thing".
>> >
>> >> thing and LLD follows suit.
>> >> R_*_IRELATIVE relocations should be eagerly resolved, so they belong
>> >> to .rela.dyn instead of .rela.plt.
>> >
>> >Ulrich and I designed/implemented IFUNC on x86 and for x86.  I consider
>> >x86 implementation of IFUC as the gold standard.
>>
>> kib from FreeBSD said
>>
>> "FreeBSD rtld does the initial pass over the plt relocations and handles
>> R_X86_64_JMP_SLOT only, If there are any R_X86_64_IRELATIVE relocks, we
>> mark the object as having such relocations. Then, we do the ireloc
>> processing, using the depth-first descend. We handle all IRELOCs for
>> dependent objects before doing it for dependee. There, we iterate over
>> all plt relocs to select IRELOCs."
>>
>> I pondered at this comment
>>
>> /*
>>   * The handling of R_MACHINE_IRELATIVE relocations and jumpslots
>>   * referencing STT_GNU_IFUNC symbols is postponed till the other
>>   * relocations are done.  The indirect functions specified as
>>   * ifunc are allowed to call other symbols, so we need to have
>>   * objects relocated before asking for resolution from indirects.
>>   *
>>   * The R_MACHINE_IRELATIVE slots are resolved in greedy fashion,
>>   * instead of the usual lazy handling of PLT slots.  It is
>>   * consistent with how GNU does it.
>>   */
>>
>> and re-read https://sourceware.org/glibc/wiki/GNU_IFUNC
>>
>> "This may work on x86_64 where the R_*_IRELATIVE relocations happen in
>> DT_JMPREL after the DT_REL* relocations, but that is no guarantee that it will
>> work on AArch64, PPC64, or other architectures that are slightly different.
>> Such fundamental limitations may be lifted at a future point."
>>
>> I think adopting the FreeBSD approach can make IRELATIVE more robust, even for
>> x86. IRELATIVE is still eager resolved, just postponed after other relocations.
>> Fixing this property in glibc will improve rubustness/flexibility of ifunc
>> resolvers and freeing linkers the responsibility to order IRELATIVE in a
>> particular position.
>>
>> Pioneering on one feature gives the designer respect, yet the designer can only
>> earn authority by demonstrating the consideration of all sort of implication.
>>
>
>On Linux/x86, lld is incompatible with ld.so on this particular IFUNC feature.
>We have 3 choices:
>
>1. Ignore it.  But it means that if lld is used to build glibc, we don't know if
>this feature works or not.

Let's ignore it :)

It's just 2 tests, representing a corner case of IRELATIVE, which is
unreliable on non-x86 (as documented) and x86 (see below) anyway.

>2. Change glibc to make it compatible with lld.
>3. Change lld to make it compatible with glibc.
>
>The FreeBSD scheme is not wrong.  But it is a workaround in glibc
>for a linker bug unless it also fixes other IFUNC issues on Linux/x86.

Let me try convincing you that glibc should be fixed:)

   // a.c
   #include <stdio.h>

   int a_impl() { return 42; }
   void *a_resolver() {
     puts("a_resolver");
     return (void *)a_impl;
   }
   int a() __attribute__((ifunc("a_resolver")));

   // .rela.dyn.rel => R_X86_64_64 referencing STT_GNU_IFUNC in .rela.dyn
   int (*fptr_a)() = a;

   int main() { printf("%d\n", a()); }

OK, let's compile with gcc and link with GNU ld:

% cc -fpie -c a.c; cc -fuse-ld=bfd -pie a.o -o a; ./a
[1]    170657 segmentation fault  ./a

Oops. The segfault is very similar to the 2 ld.lld FAIL.

Now, you may say, we can change GNU ld to emit R_X86_64_IRELATIVE instead of R_X86_64_64.

Then let's try this:

   // b.c
   #include <stdio.h>

   int b_impl() { return 42; }
   void *b_resolver() {
     puts("b resolver");
     return (void *)b_impl;
   }
   int b() __attribute__((ifunc("b_resolver")));

   int (*fptr_b)() = b;

cc b.c -fpic -shared -o b.so
Make it a DT_NEEDED of a and see the crash again. b is preemptible so IRELATIVE is not correct.


If glibc adopts the FreeBSD model, then all these will be good, along with LLD's .rela.dyn IRELATIVE.
An ifunc resolver can call functions defined in an arbitrary DT_NEEDED.
  
H.J. Lu Aug. 9, 2021, 5:58 p.m. UTC | #7
On Sat, Aug 7, 2021 at 9:17 PM Fāng-ruì Sòng <maskray@google.com> wrote:
>
>
>
> On 2021-08-07, H.J. Lu wrote:
> >On Fri, Aug 6, 2021 at 5:48 PM Fāng-ruì Sòng <maskray@google.com> wrote:
> >>
> >> On 2021-08-05, H.J. Lu wrote:
> >> >On Thu, Aug 5, 2021 at 9:43 AM Fāng-ruì Sòng <maskray@google.com> wrote:
> >> >>
> >> >> On Thu, Aug 5, 2021 at 9:34 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >> >> >
> >> >> > On Thu, Aug 5, 2021 at 9:29 AM Fangrui Song via Libc-alpha
> >> >> > <libc-alpha@sourceware.org> wrote:
> >> >> > >
> >> >> > > When using LLD (LLVM linker) as the linker, configure prints a confusing
> >> >> > > message.
> >> >> > >
> >> >> > >     *** These critical programs are missing or too old: GNU ld
> >> >> > >
> >> >> > > LLD>=13.0.0 can build glibc --enable-static-pie. (8.0.0 needs one
> >> >> > > workaround for -Wl,-defsym=_begin=0. 9.0.0 works with
> >> >> > > --disable-static-pie).
> >> >> > >
> >> >> > > With BZ #28153 (glibc bug exposed by testing with LLD) fixed,
> >> >> > > `make check` only has 2 more failures with LLD than with GNU ld:
> >> >> > > BZ #28154 (LLD follows the PowerPC port of GNU ld for ifunc by
> >> >> > > placing IRELATIVE relocations in .rela.dyn).
> >> >> >
> >> >> > This is an lld bug, similar to:
> >> >> >
> >> >> > https://sourceware.org/bugzilla/show_bug.cgi?id=13302
> >> >> >
> >> >> > Please fix it at least on x86.
> >> >>
> >> >> I am afraid that I disagree. The PowerPC port of GNU ld does the right
> >> >
> >> >This is just one opinion and it doesn't make it "the right thing".
> >> >
> >> >> thing and LLD follows suit.
> >> >> R_*_IRELATIVE relocations should be eagerly resolved, so they belong
> >> >> to .rela.dyn instead of .rela.plt.
> >> >
> >> >Ulrich and I designed/implemented IFUNC on x86 and for x86.  I consider
> >> >x86 implementation of IFUC as the gold standard.
> >>
> >> kib from FreeBSD said
> >>
> >> "FreeBSD rtld does the initial pass over the plt relocations and handles
> >> R_X86_64_JMP_SLOT only, If there are any R_X86_64_IRELATIVE relocks, we
> >> mark the object as having such relocations. Then, we do the ireloc
> >> processing, using the depth-first descend. We handle all IRELOCs for
> >> dependent objects before doing it for dependee. There, we iterate over
> >> all plt relocs to select IRELOCs."
> >>
> >> I pondered at this comment
> >>
> >> /*
> >>   * The handling of R_MACHINE_IRELATIVE relocations and jumpslots
> >>   * referencing STT_GNU_IFUNC symbols is postponed till the other
> >>   * relocations are done.  The indirect functions specified as
> >>   * ifunc are allowed to call other symbols, so we need to have
> >>   * objects relocated before asking for resolution from indirects.
> >>   *
> >>   * The R_MACHINE_IRELATIVE slots are resolved in greedy fashion,
> >>   * instead of the usual lazy handling of PLT slots.  It is
> >>   * consistent with how GNU does it.
> >>   */
> >>
> >> and re-read https://sourceware.org/glibc/wiki/GNU_IFUNC
> >>
> >> "This may work on x86_64 where the R_*_IRELATIVE relocations happen in
> >> DT_JMPREL after the DT_REL* relocations, but that is no guarantee that it will
> >> work on AArch64, PPC64, or other architectures that are slightly different.
> >> Such fundamental limitations may be lifted at a future point."
> >>
> >> I think adopting the FreeBSD approach can make IRELATIVE more robust, even for
> >> x86. IRELATIVE is still eager resolved, just postponed after other relocations.
> >> Fixing this property in glibc will improve rubustness/flexibility of ifunc
> >> resolvers and freeing linkers the responsibility to order IRELATIVE in a
> >> particular position.
> >>
> >> Pioneering on one feature gives the designer respect, yet the designer can only
> >> earn authority by demonstrating the consideration of all sort of implication.
> >>
> >
> >On Linux/x86, lld is incompatible with ld.so on this particular IFUNC feature.
> >We have 3 choices:
> >
> >1. Ignore it.  But it means that if lld is used to build glibc, we don't know if
> >this feature works or not.
>
> Let's ignore it :)
>
> It's just 2 tests, representing a corner case of IRELATIVE, which is
> unreliable on non-x86 (as documented) and x86 (see below) anyway.
>
> >2. Change glibc to make it compatible with lld.
> >3. Change lld to make it compatible with glibc.
> >
> >The FreeBSD scheme is not wrong.  But it is a workaround in glibc
> >for a linker bug unless it also fixes other IFUNC issues on Linux/x86.
>
> Let me try convincing you that glibc should be fixed:)
>
>    // a.c
>    #include <stdio.h>
>
>    int a_impl() { return 42; }
>    void *a_resolver() {
>      puts("a_resolver");
>      return (void *)a_impl;
>    }
>    int a() __attribute__((ifunc("a_resolver")));
>
>    // .rela.dyn.rel => R_X86_64_64 referencing STT_GNU_IFUNC in .rela.dyn
>    int (*fptr_a)() = a;
>
>    int main() { printf("%d\n", a()); }
>
> OK, let's compile with gcc and link with GNU ld:
>
> % cc -fpie -c a.c; cc -fuse-ld=bfd -pie a.o -o a; ./a
> [1]    170657 segmentation fault  ./a
>
> Oops. The segfault is very similar to the 2 ld.lld FAIL.

There are restrictions on how IFUNC can be used.   If we want to
support this use case, we need to change ld.so or/and linker.

> Now, you may say, we can change GNU ld to emit R_X86_64_IRELATIVE instead of R_X86_64_64.
>
> Then let's try this:
>
>    // b.c
>    #include <stdio.h>
>
>    int b_impl() { return 42; }
>    void *b_resolver() {
>      puts("b resolver");
>      return (void *)b_impl;
>    }
>    int b() __attribute__((ifunc("b_resolver")));
>
>    int (*fptr_b)() = b;
>
> cc b.c -fpic -shared -o b.so
> Make it a DT_NEEDED of a and see the crash again. b is preemptible so IRELATIVE is not correct.

I don't believe this is the use case we want to support.

>
> If glibc adopts the FreeBSD model, then all these will be good, along with LLD's .rela.dyn IRELATIVE.
> An ifunc resolver can call functions defined in an arbitrary DT_NEEDED.
  
Fangrui Song Aug. 9, 2021, 7:58 p.m. UTC | #8
On Mon, Aug 9, 2021 at 10:59 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Sat, Aug 7, 2021 at 9:17 PM Fāng-ruì Sòng <maskray@google.com> wrote:
> >
> >
> >
> > On 2021-08-07, H.J. Lu wrote:
> > >On Fri, Aug 6, 2021 at 5:48 PM Fāng-ruì Sòng <maskray@google.com> wrote:
> > >>
> > >> On 2021-08-05, H.J. Lu wrote:
> > >> >On Thu, Aug 5, 2021 at 9:43 AM Fāng-ruì Sòng <maskray@google.com> wrote:
> > >> >>
> > >> >> On Thu, Aug 5, 2021 at 9:34 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> > >> >> >
> > >> >> > On Thu, Aug 5, 2021 at 9:29 AM Fangrui Song via Libc-alpha
> > >> >> > <libc-alpha@sourceware.org> wrote:
> > >> >> > >
> > >> >> > > When using LLD (LLVM linker) as the linker, configure prints a confusing
> > >> >> > > message.
> > >> >> > >
> > >> >> > >     *** These critical programs are missing or too old: GNU ld
> > >> >> > >
> > >> >> > > LLD>=13.0.0 can build glibc --enable-static-pie. (8.0.0 needs one
> > >> >> > > workaround for -Wl,-defsym=_begin=0. 9.0.0 works with
> > >> >> > > --disable-static-pie).
> > >> >> > >
> > >> >> > > With BZ #28153 (glibc bug exposed by testing with LLD) fixed,
> > >> >> > > `make check` only has 2 more failures with LLD than with GNU ld:
> > >> >> > > BZ #28154 (LLD follows the PowerPC port of GNU ld for ifunc by
> > >> >> > > placing IRELATIVE relocations in .rela.dyn).
> > >> >> >
> > >> >> > This is an lld bug, similar to:
> > >> >> >
> > >> >> > https://sourceware.org/bugzilla/show_bug.cgi?id=13302
> > >> >> >
> > >> >> > Please fix it at least on x86.
> > >> >>
> > >> >> I am afraid that I disagree. The PowerPC port of GNU ld does the right
> > >> >
> > >> >This is just one opinion and it doesn't make it "the right thing".
> > >> >
> > >> >> thing and LLD follows suit.
> > >> >> R_*_IRELATIVE relocations should be eagerly resolved, so they belong
> > >> >> to .rela.dyn instead of .rela.plt.
> > >> >
> > >> >Ulrich and I designed/implemented IFUNC on x86 and for x86.  I consider
> > >> >x86 implementation of IFUC as the gold standard.
> > >>
> > >> kib from FreeBSD said
> > >>
> > >> "FreeBSD rtld does the initial pass over the plt relocations and handles
> > >> R_X86_64_JMP_SLOT only, If there are any R_X86_64_IRELATIVE relocks, we
> > >> mark the object as having such relocations. Then, we do the ireloc
> > >> processing, using the depth-first descend. We handle all IRELOCs for
> > >> dependent objects before doing it for dependee. There, we iterate over
> > >> all plt relocs to select IRELOCs."
> > >>
> > >> I pondered at this comment
> > >>
> > >> /*
> > >>   * The handling of R_MACHINE_IRELATIVE relocations and jumpslots
> > >>   * referencing STT_GNU_IFUNC symbols is postponed till the other
> > >>   * relocations are done.  The indirect functions specified as
> > >>   * ifunc are allowed to call other symbols, so we need to have
> > >>   * objects relocated before asking for resolution from indirects.
> > >>   *
> > >>   * The R_MACHINE_IRELATIVE slots are resolved in greedy fashion,
> > >>   * instead of the usual lazy handling of PLT slots.  It is
> > >>   * consistent with how GNU does it.
> > >>   */
> > >>
> > >> and re-read https://sourceware.org/glibc/wiki/GNU_IFUNC
> > >>
> > >> "This may work on x86_64 where the R_*_IRELATIVE relocations happen in
> > >> DT_JMPREL after the DT_REL* relocations, but that is no guarantee that it will
> > >> work on AArch64, PPC64, or other architectures that are slightly different.
> > >> Such fundamental limitations may be lifted at a future point."
> > >>
> > >> I think adopting the FreeBSD approach can make IRELATIVE more robust, even for
> > >> x86. IRELATIVE is still eager resolved, just postponed after other relocations.
> > >> Fixing this property in glibc will improve rubustness/flexibility of ifunc
> > >> resolvers and freeing linkers the responsibility to order IRELATIVE in a
> > >> particular position.
> > >>
> > >> Pioneering on one feature gives the designer respect, yet the designer can only
> > >> earn authority by demonstrating the consideration of all sort of implication.
> > >>
> > >
> > >On Linux/x86, lld is incompatible with ld.so on this particular IFUNC feature.
> > >We have 3 choices:
> > >
> > >1. Ignore it.  But it means that if lld is used to build glibc, we don't know if
> > >this feature works or not.
> >
> > Let's ignore it :)
> >
> > It's just 2 tests, representing a corner case of IRELATIVE, which is
> > unreliable on non-x86 (as documented) and x86 (see below) anyway.
> >
> > >2. Change glibc to make it compatible with lld.
> > >3. Change lld to make it compatible with glibc.
> > >
> > >The FreeBSD scheme is not wrong.  But it is a workaround in glibc
> > >for a linker bug unless it also fixes other IFUNC issues on Linux/x86.
> >
> > Let me try convincing you that glibc should be fixed:)
> >
> >    // a.c
> >    #include <stdio.h>
> >
> >    int a_impl() { return 42; }
> >    void *a_resolver() {
> >      puts("a_resolver");
> >      return (void *)a_impl;
> >    }
> >    int a() __attribute__((ifunc("a_resolver")));
> >
> >    // .rela.dyn.rel => R_X86_64_64 referencing STT_GNU_IFUNC in .rela.dyn
> >    int (*fptr_a)() = a;
> >
> >    int main() { printf("%d\n", a()); }
> >
> > OK, let's compile with gcc and link with GNU ld:
> >
> > % cc -fpie -c a.c; cc -fuse-ld=bfd -pie a.o -o a; ./a
> > [1]    170657 segmentation fault  ./a
> >
> > Oops. The segfault is very similar to the 2 ld.lld FAIL.
>
> There are restrictions on how IFUNC can be used.   If we want to
> support this use case, we need to change ld.so or/and linker.

Since you are familiar with dynamic linking, perhaps you can offer the
ld.so fix  (postponing ifunc resolver invocation after other regular
relocations) :)

Once a separate relocation loop for ifunc is created, it is trivial
for non-x86 arch maintainers to make ifunc more reliable for their
arches.

Then users can build more trust on ifunc.


Let me consider this sub-thread a non-blocker for LLD 13.0.0 support.

> > Now, you may say, we can change GNU ld to emit R_X86_64_IRELATIVE instead of R_X86_64_64.
> >
> > Then let's try this:
> >
> >    // b.c
> >    #include <stdio.h>
> >
> >    int b_impl() { return 42; }
> >    void *b_resolver() {
> >      puts("b resolver");
> >      return (void *)b_impl;
> >    }
> >    int b() __attribute__((ifunc("b_resolver")));
> >
> >    int (*fptr_b)() = b;
> >
> > cc b.c -fpic -shared -o b.so
> > Make it a DT_NEEDED of a and see the crash again. b is preemptible so IRELATIVE is not correct.
>
> I don't believe this is the use case we want to support.

Do we have easy-to-explain words on what's supported and what's not?

> >
> > If glibc adopts the FreeBSD model, then all these will be good, along with LLD's .rela.dyn IRELATIVE.
> > An ifunc resolver can call functions defined in an arbitrary DT_NEEDED.
>
>
>
> --
> H.J.
  
H.J. Lu Aug. 10, 2021, 2:38 p.m. UTC | #9
On Mon, Aug 9, 2021 at 12:59 PM Fāng-ruì Sòng <maskray@google.com> wrote:
>
> On Mon, Aug 9, 2021 at 10:59 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Sat, Aug 7, 2021 at 9:17 PM Fāng-ruì Sòng <maskray@google.com> wrote:
> > >
> > >
> > >
> > > On 2021-08-07, H.J. Lu wrote:
> > > >On Fri, Aug 6, 2021 at 5:48 PM Fāng-ruì Sòng <maskray@google.com> wrote:
> > > >>
> > > >> On 2021-08-05, H.J. Lu wrote:
> > > >> >On Thu, Aug 5, 2021 at 9:43 AM Fāng-ruì Sòng <maskray@google.com> wrote:
> > > >> >>
> > > >> >> On Thu, Aug 5, 2021 at 9:34 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > >> >> >
> > > >> >> > On Thu, Aug 5, 2021 at 9:29 AM Fangrui Song via Libc-alpha
> > > >> >> > <libc-alpha@sourceware.org> wrote:
> > > >> >> > >
> > > >> >> > > When using LLD (LLVM linker) as the linker, configure prints a confusing
> > > >> >> > > message.
> > > >> >> > >
> > > >> >> > >     *** These critical programs are missing or too old: GNU ld
> > > >> >> > >
> > > >> >> > > LLD>=13.0.0 can build glibc --enable-static-pie. (8.0.0 needs one
> > > >> >> > > workaround for -Wl,-defsym=_begin=0. 9.0.0 works with
> > > >> >> > > --disable-static-pie).
> > > >> >> > >
> > > >> >> > > With BZ #28153 (glibc bug exposed by testing with LLD) fixed,
> > > >> >> > > `make check` only has 2 more failures with LLD than with GNU ld:
> > > >> >> > > BZ #28154 (LLD follows the PowerPC port of GNU ld for ifunc by
> > > >> >> > > placing IRELATIVE relocations in .rela.dyn).
> > > >> >> >
> > > >> >> > This is an lld bug, similar to:
> > > >> >> >
> > > >> >> > https://sourceware.org/bugzilla/show_bug.cgi?id=13302
> > > >> >> >
> > > >> >> > Please fix it at least on x86.
> > > >> >>
> > > >> >> I am afraid that I disagree. The PowerPC port of GNU ld does the right
> > > >> >
> > > >> >This is just one opinion and it doesn't make it "the right thing".
> > > >> >
> > > >> >> thing and LLD follows suit.
> > > >> >> R_*_IRELATIVE relocations should be eagerly resolved, so they belong
> > > >> >> to .rela.dyn instead of .rela.plt.
> > > >> >
> > > >> >Ulrich and I designed/implemented IFUNC on x86 and for x86.  I consider
> > > >> >x86 implementation of IFUC as the gold standard.
> > > >>
> > > >> kib from FreeBSD said
> > > >>
> > > >> "FreeBSD rtld does the initial pass over the plt relocations and handles
> > > >> R_X86_64_JMP_SLOT only, If there are any R_X86_64_IRELATIVE relocks, we
> > > >> mark the object as having such relocations. Then, we do the ireloc
> > > >> processing, using the depth-first descend. We handle all IRELOCs for
> > > >> dependent objects before doing it for dependee. There, we iterate over
> > > >> all plt relocs to select IRELOCs."
> > > >>
> > > >> I pondered at this comment
> > > >>
> > > >> /*
> > > >>   * The handling of R_MACHINE_IRELATIVE relocations and jumpslots
> > > >>   * referencing STT_GNU_IFUNC symbols is postponed till the other
> > > >>   * relocations are done.  The indirect functions specified as
> > > >>   * ifunc are allowed to call other symbols, so we need to have
> > > >>   * objects relocated before asking for resolution from indirects.
> > > >>   *
> > > >>   * The R_MACHINE_IRELATIVE slots are resolved in greedy fashion,
> > > >>   * instead of the usual lazy handling of PLT slots.  It is
> > > >>   * consistent with how GNU does it.
> > > >>   */
> > > >>
> > > >> and re-read https://sourceware.org/glibc/wiki/GNU_IFUNC
> > > >>
> > > >> "This may work on x86_64 where the R_*_IRELATIVE relocations happen in
> > > >> DT_JMPREL after the DT_REL* relocations, but that is no guarantee that it will
> > > >> work on AArch64, PPC64, or other architectures that are slightly different.
> > > >> Such fundamental limitations may be lifted at a future point."
> > > >>
> > > >> I think adopting the FreeBSD approach can make IRELATIVE more robust, even for
> > > >> x86. IRELATIVE is still eager resolved, just postponed after other relocations.
> > > >> Fixing this property in glibc will improve rubustness/flexibility of ifunc
> > > >> resolvers and freeing linkers the responsibility to order IRELATIVE in a
> > > >> particular position.
> > > >>
> > > >> Pioneering on one feature gives the designer respect, yet the designer can only
> > > >> earn authority by demonstrating the consideration of all sort of implication.
> > > >>
> > > >
> > > >On Linux/x86, lld is incompatible with ld.so on this particular IFUNC feature.
> > > >We have 3 choices:
> > > >
> > > >1. Ignore it.  But it means that if lld is used to build glibc, we don't know if
> > > >this feature works or not.
> > >
> > > Let's ignore it :)
> > >
> > > It's just 2 tests, representing a corner case of IRELATIVE, which is
> > > unreliable on non-x86 (as documented) and x86 (see below) anyway.
> > >
> > > >2. Change glibc to make it compatible with lld.
> > > >3. Change lld to make it compatible with glibc.
> > > >
> > > >The FreeBSD scheme is not wrong.  But it is a workaround in glibc
> > > >for a linker bug unless it also fixes other IFUNC issues on Linux/x86.
> > >
> > > Let me try convincing you that glibc should be fixed:)
> > >
> > >    // a.c
> > >    #include <stdio.h>
> > >
> > >    int a_impl() { return 42; }
> > >    void *a_resolver() {
> > >      puts("a_resolver");
> > >      return (void *)a_impl;
> > >    }
> > >    int a() __attribute__((ifunc("a_resolver")));
> > >
> > >    // .rela.dyn.rel => R_X86_64_64 referencing STT_GNU_IFUNC in .rela.dyn
> > >    int (*fptr_a)() = a;
> > >
> > >    int main() { printf("%d\n", a()); }
> > >
> > > OK, let's compile with gcc and link with GNU ld:
> > >
> > > % cc -fpie -c a.c; cc -fuse-ld=bfd -pie a.o -o a; ./a
> > > [1]    170657 segmentation fault  ./a
> > >
> > > Oops. The segfault is very similar to the 2 ld.lld FAIL.
> >
> > There are restrictions on how IFUNC can be used.   If we want to
> > support this use case, we need to change ld.so or/and linker.
>
> Since you are familiar with dynamic linking, perhaps you can offer the
> ld.so fix  (postponing ifunc resolver invocation after other regular
> relocations) :)

Please open a glibc bug so that we can track it.   We should first
decide if we want to support this use case.

> Once a separate relocation loop for ifunc is created, it is trivial
> for non-x86 arch maintainers to make ifunc more reliable for their
> arches.
>
> Then users can build more trust on ifunc.
>
>
> Let me consider this sub-thread a non-blocker for LLD 13.0.0 support.
>
> > > Now, you may say, we can change GNU ld to emit R_X86_64_IRELATIVE instead of R_X86_64_64.
> > >
> > > Then let's try this:
> > >
> > >    // b.c
> > >    #include <stdio.h>
> > >
> > >    int b_impl() { return 42; }
> > >    void *b_resolver() {
> > >      puts("b resolver");
> > >      return (void *)b_impl;
> > >    }
> > >    int b() __attribute__((ifunc("b_resolver")));
> > >
> > >    int (*fptr_b)() = b;
> > >
> > > cc b.c -fpic -shared -o b.so
> > > Make it a DT_NEEDED of a and see the crash again. b is preemptible so IRELATIVE is not correct.
> >
> > I don't believe this is the use case we want to support.
>
> Do we have easy-to-explain words on what's supported and what's not?

This has been a recurring topic. We should have some guidance
on IFUNC.  IFUNC was designed for glibc.  It was later extended to
other use cases.  There are limitations, like

https://sourceware.org/bugzilla/show_bug.cgi?id=20019

We need clear descriptions about how IFUNC should be used.

> > >
> > > If glibc adopts the FreeBSD model, then all these will be good, along with LLD's .rela.dyn IRELATIVE.
> > > An ifunc resolver can call functions defined in an arbitrary DT_NEEDED.
> >
> >
> >
> > --
> > H.J.
  
Fangrui Song Aug. 10, 2021, 5:42 p.m. UTC | #10
On Tue, Aug 10, 2021 at 7:38 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Mon, Aug 9, 2021 at 12:59 PM Fāng-ruì Sòng <maskray@google.com> wrote:
> >
> > On Mon, Aug 9, 2021 at 10:59 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> > >
> > > On Sat, Aug 7, 2021 at 9:17 PM Fāng-ruì Sòng <maskray@google.com> wrote:
> > > >
> > > >
> > > >
> > > > On 2021-08-07, H.J. Lu wrote:
> > > > >On Fri, Aug 6, 2021 at 5:48 PM Fāng-ruì Sòng <maskray@google.com> wrote:
> > > > >>
> > > > >> On 2021-08-05, H.J. Lu wrote:
> > > > >> >On Thu, Aug 5, 2021 at 9:43 AM Fāng-ruì Sòng <maskray@google.com> wrote:
> > > > >> >>
> > > > >> >> On Thu, Aug 5, 2021 at 9:34 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > > >> >> >
> > > > >> >> > On Thu, Aug 5, 2021 at 9:29 AM Fangrui Song via Libc-alpha
> > > > >> >> > <libc-alpha@sourceware.org> wrote:
> > > > >> >> > >
> > > > >> >> > > When using LLD (LLVM linker) as the linker, configure prints a confusing
> > > > >> >> > > message.
> > > > >> >> > >
> > > > >> >> > >     *** These critical programs are missing or too old: GNU ld
> > > > >> >> > >
> > > > >> >> > > LLD>=13.0.0 can build glibc --enable-static-pie. (8.0.0 needs one
> > > > >> >> > > workaround for -Wl,-defsym=_begin=0. 9.0.0 works with
> > > > >> >> > > --disable-static-pie).
> > > > >> >> > >
> > > > >> >> > > With BZ #28153 (glibc bug exposed by testing with LLD) fixed,
> > > > >> >> > > `make check` only has 2 more failures with LLD than with GNU ld:
> > > > >> >> > > BZ #28154 (LLD follows the PowerPC port of GNU ld for ifunc by
> > > > >> >> > > placing IRELATIVE relocations in .rela.dyn).
> > > > >> >> >
> > > > >> >> > This is an lld bug, similar to:
> > > > >> >> >
> > > > >> >> > https://sourceware.org/bugzilla/show_bug.cgi?id=13302
> > > > >> >> >
> > > > >> >> > Please fix it at least on x86.
> > > > >> >>
> > > > >> >> I am afraid that I disagree. The PowerPC port of GNU ld does the right
> > > > >> >
> > > > >> >This is just one opinion and it doesn't make it "the right thing".
> > > > >> >
> > > > >> >> thing and LLD follows suit.
> > > > >> >> R_*_IRELATIVE relocations should be eagerly resolved, so they belong
> > > > >> >> to .rela.dyn instead of .rela.plt.
> > > > >> >
> > > > >> >Ulrich and I designed/implemented IFUNC on x86 and for x86.  I consider
> > > > >> >x86 implementation of IFUC as the gold standard.
> > > > >>
> > > > >> kib from FreeBSD said
> > > > >>
> > > > >> "FreeBSD rtld does the initial pass over the plt relocations and handles
> > > > >> R_X86_64_JMP_SLOT only, If there are any R_X86_64_IRELATIVE relocks, we
> > > > >> mark the object as having such relocations. Then, we do the ireloc
> > > > >> processing, using the depth-first descend. We handle all IRELOCs for
> > > > >> dependent objects before doing it for dependee. There, we iterate over
> > > > >> all plt relocs to select IRELOCs."
> > > > >>
> > > > >> I pondered at this comment
> > > > >>
> > > > >> /*
> > > > >>   * The handling of R_MACHINE_IRELATIVE relocations and jumpslots
> > > > >>   * referencing STT_GNU_IFUNC symbols is postponed till the other
> > > > >>   * relocations are done.  The indirect functions specified as
> > > > >>   * ifunc are allowed to call other symbols, so we need to have
> > > > >>   * objects relocated before asking for resolution from indirects.
> > > > >>   *
> > > > >>   * The R_MACHINE_IRELATIVE slots are resolved in greedy fashion,
> > > > >>   * instead of the usual lazy handling of PLT slots.  It is
> > > > >>   * consistent with how GNU does it.
> > > > >>   */
> > > > >>
> > > > >> and re-read https://sourceware.org/glibc/wiki/GNU_IFUNC
> > > > >>
> > > > >> "This may work on x86_64 where the R_*_IRELATIVE relocations happen in
> > > > >> DT_JMPREL after the DT_REL* relocations, but that is no guarantee that it will
> > > > >> work on AArch64, PPC64, or other architectures that are slightly different.
> > > > >> Such fundamental limitations may be lifted at a future point."
> > > > >>
> > > > >> I think adopting the FreeBSD approach can make IRELATIVE more robust, even for
> > > > >> x86. IRELATIVE is still eager resolved, just postponed after other relocations.
> > > > >> Fixing this property in glibc will improve rubustness/flexibility of ifunc
> > > > >> resolvers and freeing linkers the responsibility to order IRELATIVE in a
> > > > >> particular position.
> > > > >>
> > > > >> Pioneering on one feature gives the designer respect, yet the designer can only
> > > > >> earn authority by demonstrating the consideration of all sort of implication.
> > > > >>
> > > > >
> > > > >On Linux/x86, lld is incompatible with ld.so on this particular IFUNC feature.
> > > > >We have 3 choices:
> > > > >
> > > > >1. Ignore it.  But it means that if lld is used to build glibc, we don't know if
> > > > >this feature works or not.
> > > >
> > > > Let's ignore it :)
> > > >
> > > > It's just 2 tests, representing a corner case of IRELATIVE, which is
> > > > unreliable on non-x86 (as documented) and x86 (see below) anyway.
> > > >
> > > > >2. Change glibc to make it compatible with lld.
> > > > >3. Change lld to make it compatible with glibc.
> > > > >
> > > > >The FreeBSD scheme is not wrong.  But it is a workaround in glibc
> > > > >for a linker bug unless it also fixes other IFUNC issues on Linux/x86.
> > > >
> > > > Let me try convincing you that glibc should be fixed:)
> > > >
> > > >    // a.c
> > > >    #include <stdio.h>
> > > >
> > > >    int a_impl() { return 42; }
> > > >    void *a_resolver() {
> > > >      puts("a_resolver");
> > > >      return (void *)a_impl;
> > > >    }
> > > >    int a() __attribute__((ifunc("a_resolver")));
> > > >
> > > >    // .rela.dyn.rel => R_X86_64_64 referencing STT_GNU_IFUNC in .rela.dyn
> > > >    int (*fptr_a)() = a;
> > > >
> > > >    int main() { printf("%d\n", a()); }
> > > >
> > > > OK, let's compile with gcc and link with GNU ld:
> > > >
> > > > % cc -fpie -c a.c; cc -fuse-ld=bfd -pie a.o -o a; ./a
> > > > [1]    170657 segmentation fault  ./a
> > > >
> > > > Oops. The segfault is very similar to the 2 ld.lld FAIL.
> > >
> > > There are restrictions on how IFUNC can be used.   If we want to
> > > support this use case, we need to change ld.so or/and linker.
> >
> > Since you are familiar with dynamic linking, perhaps you can offer the
> > ld.so fix  (postponing ifunc resolver invocation after other regular
> > relocations) :)
>
> Please open a glibc bug so that we can track it.   We should first
> decide if we want to support this use case.

https://sourceware.org/bugzilla/show_bug.cgi?id=28218
("ld.so: ifunc resolver calls a lazy PLT. When does it work?")

> > Once a separate relocation loop for ifunc is created, it is trivial
> > for non-x86 arch maintainers to make ifunc more reliable for their
> > arches.
> >
> > Then users can build more trust on ifunc.
> >
> >
> > Let me consider this sub-thread a non-blocker for LLD 13.0.0 support.
> >
> > > > Now, you may say, we can change GNU ld to emit R_X86_64_IRELATIVE instead of R_X86_64_64.
> > > >
> > > > Then let's try this:
> > > >
> > > >    // b.c
> > > >    #include <stdio.h>
> > > >
> > > >    int b_impl() { return 42; }
> > > >    void *b_resolver() {
> > > >      puts("b resolver");
> > > >      return (void *)b_impl;
> > > >    }
> > > >    int b() __attribute__((ifunc("b_resolver")));
> > > >
> > > >    int (*fptr_b)() = b;
> > > >
> > > > cc b.c -fpic -shared -o b.so
> > > > Make it a DT_NEEDED of a and see the crash again. b is preemptible so IRELATIVE is not correct.
> > >
> > > I don't believe this is the use case we want to support.
> >
> > Do we have easy-to-explain words on what's supported and what's not?
>
> This has been a recurring topic. We should have some guidance
> on IFUNC.  IFUNC was designed for glibc.  It was later extended to
> other use cases.  There are limitations, like
>
> https://sourceware.org/bugzilla/show_bug.cgi?id=20019
>
> We need clear descriptions about how IFUNC should be used.
>
> > > >
> > > > If glibc adopts the FreeBSD model, then all these will be good, along with LLD's .rela.dyn IRELATIVE.
> > > > An ifunc resolver can call functions defined in an arbitrary DT_NEEDED.
> > >
> > >
> > >
> > > --
> > > H.J.
>
>
>
> --
> H.J.
  
Fangrui Song Aug. 10, 2021, 10:19 p.m. UTC | #11
On 2021-08-05, Fangrui Song wrote:
>When using LLD (LLVM linker) as the linker, configure prints a confusing
>message.
>
>    *** These critical programs are missing or too old: GNU ld
>
>LLD>=13.0.0 can build glibc --enable-static-pie. (8.0.0 needs one
>workaround for -Wl,-defsym=_begin=0. 9.0.0 works with
>--disable-static-pie).
>
>With BZ #28153 (glibc bug exposed by testing with LLD) fixed,
>`make check` only has 2 more failures with LLD than with GNU ld:
>BZ #28154 (LLD follows the PowerPC port of GNU ld for ifunc by
>placing IRELATIVE relocations in .rela.dyn).
>The set of dynamic symbols is the same with GNU ld and LLD,
>modulo unused SHN_ABS version node symbols.
>
>For comparison, gold does not support --enable-static-pie
>yet (--no-dynamic-linker is unsupported BZ #22221), yet
>has 6 failures more than LLD. gold linked libc.so has
>larger .dynsym differences with GNU ld and LLD
>(ISTM non-default version symbols are changed to default versions
>by a version script).
>
>---
>
>I identified the lack of support of
>
>* version script on non-default version symbols
>* copy relocations on non-default version symbols
>
>in an earlier snapshot of LLD 13.0.0 and fixed them.
>The functionality of the LLD linked libc.so and ld.so looks pretty good.
>---
> configure    | 77 +++++++++++++++++++++++++++++++++++++++++++++++++---
> configure.ac | 20 ++++++++++----
> 2 files changed, 88 insertions(+), 9 deletions(-)

Ping:)

(The code/test hasn't been changed since v1.
  v2 just added BZ numbers.)

x86-64 only 2 more ifunc FAIL which tickle some weak point of ifunc implementation.

aarch64 `make-check` is fully on par with GNU ld.
   (https://sourceware.org/pipermail/libc-alpha/2021-August/130040.html)
  
Fangrui Song Aug. 23, 2021, 3:18 a.m. UTC | #12
On Tue, Aug 10, 2021 at 3:19 PM Fangrui Song <maskray@google.com> wrote:
>
> On 2021-08-05, Fangrui Song wrote:
> >When using LLD (LLVM linker) as the linker, configure prints a confusing
> >message.
> >
> >    *** These critical programs are missing or too old: GNU ld
> >
> >LLD>=13.0.0 can build glibc --enable-static-pie. (8.0.0 needs one
> >workaround for -Wl,-defsym=_begin=0. 9.0.0 works with
> >--disable-static-pie).
> >
> >With BZ #28153 (glibc bug exposed by testing with LLD) fixed,
> >`make check` only has 2 more failures with LLD than with GNU ld:
> >BZ #28154 (LLD follows the PowerPC port of GNU ld for ifunc by
> >placing IRELATIVE relocations in .rela.dyn).
> >The set of dynamic symbols is the same with GNU ld and LLD,
> >modulo unused SHN_ABS version node symbols.
> >
> >For comparison, gold does not support --enable-static-pie
> >yet (--no-dynamic-linker is unsupported BZ #22221), yet
> >has 6 failures more than LLD. gold linked libc.so has
> >larger .dynsym differences with GNU ld and LLD
> >(ISTM non-default version symbols are changed to default versions
> >by a version script).
> >
> >---
> >
> >I identified the lack of support of
> >
> >* version script on non-default version symbols
> >* copy relocations on non-default version symbols
> >
> >in an earlier snapshot of LLD 13.0.0 and fixed them.
> >The functionality of the LLD linked libc.so and ld.so looks pretty good.
> >---
> > configure    | 77 +++++++++++++++++++++++++++++++++++++++++++++++++---
> > configure.ac | 20 ++++++++++----
> > 2 files changed, 88 insertions(+), 9 deletions(-)
>
> Ping:)
>
> (The code/test hasn't been changed since v1.
>   v2 just added BZ numbers.)
>
> x86-64 only 2 more ifunc FAIL which tickle some weak point of ifunc implementation.
>
> aarch64 `make-check` is fully on par with GNU ld.
>    (https://sourceware.org/pipermail/libc-alpha/2021-August/130040.html)

Ping^2

("elf: Replace .tls_common with .tbss definition [BZ #28152]" has been
subsumed into a tls-macros.h removal patch.)
  
Fangrui Song Aug. 24, 2021, 5:05 p.m. UTC | #13
On Sun, Aug 22, 2021 at 8:18 PM Fāng-ruì Sòng <maskray@google.com> wrote:
>
> On Tue, Aug 10, 2021 at 3:19 PM Fangrui Song <maskray@google.com> wrote:
> >
> > On 2021-08-05, Fangrui Song wrote:
> > >When using LLD (LLVM linker) as the linker, configure prints a confusing
> > >message.
> > >
> > >    *** These critical programs are missing or too old: GNU ld
> > >
> > >LLD>=13.0.0 can build glibc --enable-static-pie. (8.0.0 needs one
> > >workaround for -Wl,-defsym=_begin=0. 9.0.0 works with
> > >--disable-static-pie).
> > >
> > >With BZ #28153 (glibc bug exposed by testing with LLD) fixed,
> > >`make check` only has 2 more failures with LLD than with GNU ld:
> > >BZ #28154 (LLD follows the PowerPC port of GNU ld for ifunc by
> > >placing IRELATIVE relocations in .rela.dyn).
> > >The set of dynamic symbols is the same with GNU ld and LLD,
> > >modulo unused SHN_ABS version node symbols.
> > >
> > >For comparison, gold does not support --enable-static-pie
> > >yet (--no-dynamic-linker is unsupported BZ #22221), yet
> > >has 6 failures more than LLD. gold linked libc.so has
> > >larger .dynsym differences with GNU ld and LLD
> > >(ISTM non-default version symbols are changed to default versions
> > >by a version script).
> > >
> > >---
> > >
> > >I identified the lack of support of
> > >
> > >* version script on non-default version symbols
> > >* copy relocations on non-default version symbols
> > >
> > >in an earlier snapshot of LLD 13.0.0 and fixed them.
> > >The functionality of the LLD linked libc.so and ld.so looks pretty good.
> > >---
> > > configure    | 77 +++++++++++++++++++++++++++++++++++++++++++++++++---
> > > configure.ac | 20 ++++++++++----
> > > 2 files changed, 88 insertions(+), 9 deletions(-)
> >
> > Ping:)
> >
> > (The code/test hasn't been changed since v1.
> >   v2 just added BZ numbers.)
> >
> > x86-64 only 2 more ifunc FAIL which tickle some weak point of ifunc implementation.
> >
> > aarch64 `make-check` is fully on par with GNU ld.
> >    (https://sourceware.org/pipermail/libc-alpha/2021-August/130040.html)
>
> Ping^2
>
> ("elf: Replace .tls_common with .tbss definition [BZ #28152]" has been
> subsumed into a tls-macros.h removal patch.)

This is now the only needed commit.

aarch64 and ppc64le look on par.
x86-64 just has 2 more FAIL due to ld.so's intrinsic lack of ifunc robustness.
  
Fangrui Song Aug. 30, 2021, 7:52 p.m. UTC | #14
On Tue, Aug 24, 2021 at 10:05 AM Fāng-ruì Sòng <maskray@google.com> wrote:
>
> On Sun, Aug 22, 2021 at 8:18 PM Fāng-ruì Sòng <maskray@google.com> wrote:
> >
> > On Tue, Aug 10, 2021 at 3:19 PM Fangrui Song <maskray@google.com> wrote:
> > >
> > > On 2021-08-05, Fangrui Song wrote:
> > > >When using LLD (LLVM linker) as the linker, configure prints a confusing
> > > >message.
> > > >
> > > >    *** These critical programs are missing or too old: GNU ld
> > > >
> > > >LLD>=13.0.0 can build glibc --enable-static-pie. (8.0.0 needs one
> > > >workaround for -Wl,-defsym=_begin=0. 9.0.0 works with
> > > >--disable-static-pie).
> > > >
> > > >With BZ #28153 (glibc bug exposed by testing with LLD) fixed,
> > > >`make check` only has 2 more failures with LLD than with GNU ld:
> > > >BZ #28154 (LLD follows the PowerPC port of GNU ld for ifunc by
> > > >placing IRELATIVE relocations in .rela.dyn).
> > > >The set of dynamic symbols is the same with GNU ld and LLD,
> > > >modulo unused SHN_ABS version node symbols.
> > > >
> > > >For comparison, gold does not support --enable-static-pie
> > > >yet (--no-dynamic-linker is unsupported BZ #22221), yet
> > > >has 6 failures more than LLD. gold linked libc.so has
> > > >larger .dynsym differences with GNU ld and LLD
> > > >(ISTM non-default version symbols are changed to default versions
> > > >by a version script).
> > > >
> > > >---
> > > >
> > > >I identified the lack of support of
> > > >
> > > >* version script on non-default version symbols
> > > >* copy relocations on non-default version symbols
> > > >
> > > >in an earlier snapshot of LLD 13.0.0 and fixed them.
> > > >The functionality of the LLD linked libc.so and ld.so looks pretty good.
> > > >---
> > > > configure    | 77 +++++++++++++++++++++++++++++++++++++++++++++++++---
> > > > configure.ac | 20 ++++++++++----
> > > > 2 files changed, 88 insertions(+), 9 deletions(-)
> > >
> > > Ping:)
> > >
> > > (The code/test hasn't been changed since v1.
> > >   v2 just added BZ numbers.)
> > >
> > > x86-64 only 2 more ifunc FAIL which tickle some weak point of ifunc implementation.
> > >
> > > aarch64 `make-check` is fully on par with GNU ld.
> > >    (https://sourceware.org/pipermail/libc-alpha/2021-August/130040.html)
> >
> > Ping^2
> >
> > ("elf: Replace .tls_common with .tbss definition [BZ #28152]" has been
> > subsumed into a tls-macros.h removal patch.)
>
> This is now the only needed commit.
>
> aarch64 and ppc64le look on par.
> x86-64 just has 2 more FAIL due to ld.so's intrinsic lack of ifunc robustness.


Ping^4. I'll push if nobody objects.
  
Adhemerval Zanella Netto Aug. 30, 2021, 8:01 p.m. UTC | #15
On 30/08/2021 16:52, Fāng-ruì Sòng via Libc-alpha wrote:
> On Tue, Aug 24, 2021 at 10:05 AM Fāng-ruì Sòng <maskray@google.com> wrote:
>>
>> On Sun, Aug 22, 2021 at 8:18 PM Fāng-ruì Sòng <maskray@google.com> wrote:
>>>
>>> On Tue, Aug 10, 2021 at 3:19 PM Fangrui Song <maskray@google.com> wrote:
>>>>
>>>> On 2021-08-05, Fangrui Song wrote:
>>>>> When using LLD (LLVM linker) as the linker, configure prints a confusing
>>>>> message.
>>>>>
>>>>>    *** These critical programs are missing or too old: GNU ld
>>>>>
>>>>> LLD>=13.0.0 can build glibc --enable-static-pie. (8.0.0 needs one
>>>>> workaround for -Wl,-defsym=_begin=0. 9.0.0 works with
>>>>> --disable-static-pie).
>>>>>
>>>>> With BZ #28153 (glibc bug exposed by testing with LLD) fixed,
>>>>> `make check` only has 2 more failures with LLD than with GNU ld:
>>>>> BZ #28154 (LLD follows the PowerPC port of GNU ld for ifunc by
>>>>> placing IRELATIVE relocations in .rela.dyn).
>>>>> The set of dynamic symbols is the same with GNU ld and LLD,
>>>>> modulo unused SHN_ABS version node symbols.
>>>>>
>>>>> For comparison, gold does not support --enable-static-pie
>>>>> yet (--no-dynamic-linker is unsupported BZ #22221), yet
>>>>> has 6 failures more than LLD. gold linked libc.so has
>>>>> larger .dynsym differences with GNU ld and LLD
>>>>> (ISTM non-default version symbols are changed to default versions
>>>>> by a version script).
>>>>>
>>>>> ---
>>>>>
>>>>> I identified the lack of support of
>>>>>
>>>>> * version script on non-default version symbols
>>>>> * copy relocations on non-default version symbols
>>>>>
>>>>> in an earlier snapshot of LLD 13.0.0 and fixed them.
>>>>> The functionality of the LLD linked libc.so and ld.so looks pretty good.
>>>>> ---
>>>>> configure    | 77 +++++++++++++++++++++++++++++++++++++++++++++++++---
>>>>> configure.ac | 20 ++++++++++----
>>>>> 2 files changed, 88 insertions(+), 9 deletions(-)
>>>>
>>>> Ping:)
>>>>
>>>> (The code/test hasn't been changed since v1.
>>>>   v2 just added BZ numbers.)
>>>>
>>>> x86-64 only 2 more ifunc FAIL which tickle some weak point of ifunc implementation.
>>>>
>>>> aarch64 `make-check` is fully on par with GNU ld.
>>>>    (https://sourceware.org/pipermail/libc-alpha/2021-August/130040.html)
>>>
>>> Ping^2
>>>
>>> ("elf: Replace .tls_common with .tbss definition [BZ #28152]" has been
>>> subsumed into a tls-macros.h removal patch.)
>>
>> This is now the only needed commit.
>>
>> aarch64 and ppc64le look on par.
>> x86-64 just has 2 more FAIL due to ld.so's intrinsic lack of ifunc robustness.
> 
> 
> Ping^4. I'll push if nobody objects.

H.J has raised some objections and referenced BZ#28218 [1].  Are the
two tests still occurring with lld? If it were the case I think we
should at least xfailing then by returning FAIL_UNSUPPORTED if lld
is being used the linker.

[1] https://sourceware.org/bugzilla/show_bug.cgi?id=28218
  
Fangrui Song Aug. 31, 2021, 9:24 p.m. UTC | #16
On Mon, Aug 30, 2021 at 1:01 PM Adhemerval Zanella
<adhemerval.zanella@linaro.org> wrote:
>
>
>
> On 30/08/2021 16:52, Fāng-ruì Sòng via Libc-alpha wrote:
> > On Tue, Aug 24, 2021 at 10:05 AM Fāng-ruì Sòng <maskray@google.com> wrote:
> >>
> >> On Sun, Aug 22, 2021 at 8:18 PM Fāng-ruì Sòng <maskray@google.com> wrote:
> >>>
> >>> On Tue, Aug 10, 2021 at 3:19 PM Fangrui Song <maskray@google.com> wrote:
> >>>>
> >>>> On 2021-08-05, Fangrui Song wrote:
> >>>>> When using LLD (LLVM linker) as the linker, configure prints a confusing
> >>>>> message.
> >>>>>
> >>>>>    *** These critical programs are missing or too old: GNU ld
> >>>>>
> >>>>> LLD>=13.0.0 can build glibc --enable-static-pie. (8.0.0 needs one
> >>>>> workaround for -Wl,-defsym=_begin=0. 9.0.0 works with
> >>>>> --disable-static-pie).
> >>>>>
> >>>>> With BZ #28153 (glibc bug exposed by testing with LLD) fixed,
> >>>>> `make check` only has 2 more failures with LLD than with GNU ld:
> >>>>> BZ #28154 (LLD follows the PowerPC port of GNU ld for ifunc by
> >>>>> placing IRELATIVE relocations in .rela.dyn).
> >>>>> The set of dynamic symbols is the same with GNU ld and LLD,
> >>>>> modulo unused SHN_ABS version node symbols.
> >>>>>
> >>>>> For comparison, gold does not support --enable-static-pie
> >>>>> yet (--no-dynamic-linker is unsupported BZ #22221), yet
> >>>>> has 6 failures more than LLD. gold linked libc.so has
> >>>>> larger .dynsym differences with GNU ld and LLD
> >>>>> (ISTM non-default version symbols are changed to default versions
> >>>>> by a version script).
> >>>>>
> >>>>> ---
> >>>>>
> >>>>> I identified the lack of support of
> >>>>>
> >>>>> * version script on non-default version symbols
> >>>>> * copy relocations on non-default version symbols
> >>>>>
> >>>>> in an earlier snapshot of LLD 13.0.0 and fixed them.
> >>>>> The functionality of the LLD linked libc.so and ld.so looks pretty good.
> >>>>> ---
> >>>>> configure    | 77 +++++++++++++++++++++++++++++++++++++++++++++++++---
> >>>>> configure.ac | 20 ++++++++++----
> >>>>> 2 files changed, 88 insertions(+), 9 deletions(-)
> >>>>
> >>>> Ping:)
> >>>>
> >>>> (The code/test hasn't been changed since v1.
> >>>>   v2 just added BZ numbers.)
> >>>>
> >>>> x86-64 only 2 more ifunc FAIL which tickle some weak point of ifunc implementation.
> >>>>
> >>>> aarch64 `make-check` is fully on par with GNU ld.
> >>>>    (https://sourceware.org/pipermail/libc-alpha/2021-August/130040.html)
> >>>
> >>> Ping^2
> >>>
> >>> ("elf: Replace .tls_common with .tbss definition [BZ #28152]" has been
> >>> subsumed into a tls-macros.h removal patch.)
> >>
> >> This is now the only needed commit.
> >>
> >> aarch64 and ppc64le look on par.
> >> x86-64 just has 2 more FAIL due to ld.so's intrinsic lack of ifunc robustness.
> >
> >
> > Ping^4. I'll push if nobody objects.
>
> H.J has raised some objections and referenced BZ#28218 [1].  Are the
> two tests still occurring with lld? If it were the case I think we
> should at least xfailing then by returning FAIL_UNSUPPORTED if lld
> is being used the linker.
>
> [1] https://sourceware.org/bugzilla/show_bug.cgi?id=28218

I'll use https://sourceware.org/pipermail/libc-alpha/2021-August/130637.html
which XFAIL the two ifunc tests.
  

Patch

diff --git a/configure b/configure
index 9b966196d4..050f1a29cf 100755
--- a/configure
+++ b/configure
@@ -4664,9 +4664,10 @@  if test $ac_verc_fail = yes; then
 fi
 
 
-if test -n "`$LD --version | sed -n 's/^GNU \(gold\).*$/\1/p'`"; then
+case $($LD --version) in
+  "GNU gold"*)
   # Accept gold 1.14 or higher
-  for ac_prog in $LD
+    for ac_prog in $LD
 do
   # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
@@ -4729,8 +4730,75 @@  if test $ac_verc_fail = yes; then
   LD=: critic_missing="$critic_missing GNU gold"
 fi
 
+    ;;
+  "LLD"*)
+  # Accept LLD 13.0.0 or higher
+    for ac_prog in $LD
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_LD+:} false; then :
+  $as_echo_n "(cached) " >&6
 else
-  for ac_prog in $LD
+  if test -n "$LD"; then
+  ac_cv_prog_LD="$LD" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_LD="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+LD=$ac_cv_prog_LD
+if test -n "$LD"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
+$as_echo "$LD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$LD" && break
+done
+
+if test -z "$LD"; then
+  ac_verc_fail=yes
+else
+  # Found it, now check the version.
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking version of $LD" >&5
+$as_echo_n "checking version of $LD... " >&6; }
+  ac_prog_version=`$LD --version 2>&1 | sed -n 's/^.*LLD.* \([0-9][0-9]*\.[0-9.]*\).*$/\1/p'`
+  case $ac_prog_version in
+    '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
+    1[3-9].*|[2-9][0-9].*)
+       ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
+    *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;;
+
+  esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_prog_version" >&5
+$as_echo "$ac_prog_version" >&6; }
+fi
+if test $ac_verc_fail = yes; then
+  LD=: critic_missing="$critic_missing LLD"
+fi
+
+    ;;
+  *)
+    for ac_prog in $LD
 do
   # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
@@ -4793,7 +4861,8 @@  if test $ac_verc_fail = yes; then
   LD=: critic_missing="$critic_missing GNU ld"
 fi
 
-fi
+    ;;
+esac
 
 # These programs are version sensitive.
 for ac_prog in gnumake gmake make
diff --git a/configure.ac b/configure.ac
index 17a4c9a1ab..5632277f9c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -995,18 +995,28 @@  AC_CHECK_PROG_VER(AS, $AS, --version,
 		  [2.1[0-9][0-9]*|2.2[5-9]*|2.[3-9][0-9]*|[3-9].*|[1-9][0-9]*],
 		  AS=: critic_missing="$critic_missing as")
 
-if test -n "`$LD --version | sed -n 's/^GNU \(gold\).*$/\1/p'`"; then
+case $($LD --version) in
+  "GNU gold"*)
   # Accept gold 1.14 or higher
-  AC_CHECK_PROG_VER(LD, $LD, --version,
+    AC_CHECK_PROG_VER(LD, $LD, --version,
 		    [GNU gold.* \([0-9][0-9]*\.[0-9.]*\)],
 		    [1.1[4-9]*|1.[2-9][0-9]*|1.1[0-9][0-9]*|[2-9].*|[1-9][0-9]*],
 		    LD=: critic_missing="$critic_missing GNU gold")
-else
-  AC_CHECK_PROG_VER(LD, $LD, --version,
+    ;;
+  "LLD"*)
+  # Accept LLD 13.0.0 or higher
+    AC_CHECK_PROG_VER(LD, $LD, --version,
+		    [LLD.* \([0-9][0-9]*\.[0-9.]*\)],
+		    [1[3-9].*|[2-9][0-9].*],
+		    LD=: critic_missing="$critic_missing LLD")
+    ;;
+  *)
+    AC_CHECK_PROG_VER(LD, $LD, --version,
 		    [GNU ld.* \([0-9][0-9]*\.[0-9.]*\)],
 		    [2.1[0-9][0-9]*|2.2[5-9]*|2.[3-9][0-9]*|[3-9].*|[1-9][0-9]*],
 		    LD=: critic_missing="$critic_missing GNU ld")
-fi
+    ;;
+esac
 
 # These programs are version sensitive.
 AC_CHECK_PROG_VER(MAKE, gnumake gmake make, --version,