ld: Skip the LTO archive member only for the earlier DSO

Message ID 20250408201002.383836-1-hjl.tools@gmail.com
State New
Headers
Series ld: Skip the LTO archive member only for the earlier DSO |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_binutils_check--master-arm fail Patch failed to apply
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 fail Patch failed to apply

Commit Message

H.J. Lu April 8, 2025, 8:10 p.m. UTC
  commit 2707d55e539ef323dd14a1293e762bf3d9739ee7
Author: Michael Matz <matz@suse.de>
Date:   Mon Mar 31 15:57:08 2025 +0200

skipped the LTO archive member even when the earlier item is also an
archive.  Instead, skip the LTO archive member only if the earlier item
is a shared library.

bfd/

	PR ld/32846
	PR ld/32854
	* elflink.c (elf_link_add_archive_symbols): Skip the LTO archive
	member only if the earlier item is a shared library.

ld/

	PR ld/32846
	PR ld/32854
	* testsuite/ld-plugin/lto.exp: Run ld/32846 test.
	* testsuite/ld-plugin/pr32846a.c: New file.
	* testsuite/ld-plugin/pr32846b.c: Likewise.
	* testsuite/ld-plugin/pr32846c.c: Likewise.
	* testsuite/ld-plugin/pr32846d.c: Likewise.
	* testsuite/ld-plugin/pr32846e.c: Likewise.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
---
 bfd/elflink.c                     |  8 +++++---
 ld/testsuite/ld-plugin/lto.exp    | 32 +++++++++++++++++++++++++++++++
 ld/testsuite/ld-plugin/pr32846a.c |  6 ++++++
 ld/testsuite/ld-plugin/pr32846b.c |  4 ++++
 ld/testsuite/ld-plugin/pr32846c.c |  6 ++++++
 ld/testsuite/ld-plugin/pr32846d.c | 12 ++++++++++++
 ld/testsuite/ld-plugin/pr32846e.c |  4 ++++
 7 files changed, 69 insertions(+), 3 deletions(-)
 create mode 100644 ld/testsuite/ld-plugin/pr32846a.c
 create mode 100644 ld/testsuite/ld-plugin/pr32846b.c
 create mode 100644 ld/testsuite/ld-plugin/pr32846c.c
 create mode 100644 ld/testsuite/ld-plugin/pr32846d.c
 create mode 100644 ld/testsuite/ld-plugin/pr32846e.c
  

Comments

Sam James April 9, 2025, 4:52 a.m. UTC | #1
"H.J. Lu" <hjl.tools@gmail.com> writes:

> commit 2707d55e539ef323dd14a1293e762bf3d9739ee7
> Author: Michael Matz <matz@suse.de>
> Date:   Mon Mar 31 15:57:08 2025 +0200
>
> skipped the LTO archive member even when the earlier item is also an
> archive.  Instead, skip the LTO archive member only if the earlier item
> is a shared library.

Thanks. kmod now works, I'll test others for the next day or so.

>
> bfd/
>
> 	PR ld/32846
> 	PR ld/32854
> 	* elflink.c (elf_link_add_archive_symbols): Skip the LTO archive
> 	member only if the earlier item is a shared library.
>
> ld/
>
> 	PR ld/32846
> 	PR ld/32854
> 	* testsuite/ld-plugin/lto.exp: Run ld/32846 test.
> 	* testsuite/ld-plugin/pr32846a.c: New file.
> 	* testsuite/ld-plugin/pr32846b.c: Likewise.
> 	* testsuite/ld-plugin/pr32846c.c: Likewise.
> 	* testsuite/ld-plugin/pr32846d.c: Likewise.
> 	* testsuite/ld-plugin/pr32846e.c: Likewise.
>
> Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
> ---
>  bfd/elflink.c                     |  8 +++++---
>  ld/testsuite/ld-plugin/lto.exp    | 32 +++++++++++++++++++++++++++++++
>  ld/testsuite/ld-plugin/pr32846a.c |  6 ++++++
>  ld/testsuite/ld-plugin/pr32846b.c |  4 ++++
>  ld/testsuite/ld-plugin/pr32846c.c |  6 ++++++
>  ld/testsuite/ld-plugin/pr32846d.c | 12 ++++++++++++
>  ld/testsuite/ld-plugin/pr32846e.c |  4 ++++
>  7 files changed, 69 insertions(+), 3 deletions(-)
>  create mode 100644 ld/testsuite/ld-plugin/pr32846a.c
>  create mode 100644 ld/testsuite/ld-plugin/pr32846b.c
>  create mode 100644 ld/testsuite/ld-plugin/pr32846c.c
>  create mode 100644 ld/testsuite/ld-plugin/pr32846d.c
>  create mode 100644 ld/testsuite/ld-plugin/pr32846e.c
>
> diff --git a/bfd/elflink.c b/bfd/elflink.c
> index a76e8e38da7..2ac12144990 100644
> --- a/bfd/elflink.c
> +++ b/bfd/elflink.c
> @@ -6290,8 +6290,8 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
>  		    continue;
>  
>  		  /* In the pre-LTO-plugin pass we must not mistakenly
> -		     include this archive member if an earlier BFD
> -		     defined this symbol.  */
> +		     include this archive member if an earlier shared
> +		     library defined this symbol.  */
>  		  struct elf_link_hash_table *htab = elf_hash_table (info);
>  		  if (htab->first_hash)
>  		    {
> @@ -6299,7 +6299,9 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
>  			  = ((struct elf_link_first_hash_entry *)
>  			     bfd_hash_lookup (htab->first_hash, symdef->name,
>  					      false, false));
> -		      if (e && e->abfd != abfd)
> +		      if (e
> +			  && (e->abfd->flags & DYNAMIC) != 0
> +			  && e->abfd != abfd)
>  			continue;
>  		    }
>  		}
> diff --git a/ld/testsuite/ld-plugin/lto.exp b/ld/testsuite/ld-plugin/lto.exp
> index 93491902674..726dd933329 100644
> --- a/ld/testsuite/ld-plugin/lto.exp
> +++ b/ld/testsuite/ld-plugin/lto.exp
> @@ -1212,6 +1212,38 @@ if { [is_elf_format] } {
>  
>  if { [is_elf_format] && [check_lto_shared_available] } {
>      run_ld_link_exec_tests $lto_run_elf_shared_tests
> +    if { [check_lto_fat_available] } {
> +	run_cc_link_tests [list \
> +	    [list \
> +	    	"Build libpr32846a.a" \
> +	    	"$plug_opt" "-O2 -flto $lto_no_fat" \
> +	    	{pr32846a.c pr32846b.c} {} "libpr32846a.a" \
> +	    ] \
> +	    [list \
> +		"Build libpr32846b.a" \
> +	    	"$plug_opt" "-O2 -flto $lto_no_fat" \
> +		{pr32846a.c pr32846b.c pr32846c.c} {} "libpr32846b.a" \
> +	    ] \
> +	    [list \
> +	    	"Build pr32846d.o" \
> +	    	"$plug_opt" "-O2 -flto $lto_no_fat" \
> +	    	{pr32846d.c} {} \
> +	    ] \
> +	    [list \
> +	    	"Build pr32846e.o" \
> +	    	"$plug_opt" "-O2 -flto $lto_no_fat" \
> +	    	{pr32846e.c} {} \
> +	    ] \
> +	    [list \
> +		"Build pr32846" \
> +		"-shared -fPIC -O2 -flto $lto_no_fat -Wl,--no-undefined \
> +		 tmpdir/pr32846d.o tmpdir/libpr32846a.a \
> +		 tmpdir/libpr32846b.a tmpdir/pr32846e.o" \
> +		"-O2 -fPIC -flto $lto_no_fat" \
> +		{dummy.c} {} "pr32846" \
> +	    ] \
> +	] \
> +    }
>  }
>  
>  proc pr20103 {cflags libs} {
> diff --git a/ld/testsuite/ld-plugin/pr32846a.c b/ld/testsuite/ld-plugin/pr32846a.c
> new file mode 100644
> index 00000000000..8c161711bd9
> --- /dev/null
> +++ b/ld/testsuite/ld-plugin/pr32846a.c
> @@ -0,0 +1,6 @@
> +extern void mkdir_p (void);
> +void
> +mkdir_parents (void)
> +{
> +  mkdir_p ();
> +}
> diff --git a/ld/testsuite/ld-plugin/pr32846b.c b/ld/testsuite/ld-plugin/pr32846b.c
> new file mode 100644
> index 00000000000..9776a372d7a
> --- /dev/null
> +++ b/ld/testsuite/ld-plugin/pr32846b.c
> @@ -0,0 +1,4 @@
> +void
> +hash_new (void)
> +{
> +}
> diff --git a/ld/testsuite/ld-plugin/pr32846c.c b/ld/testsuite/ld-plugin/pr32846c.c
> new file mode 100644
> index 00000000000..f87cffb8865
> --- /dev/null
> +++ b/ld/testsuite/ld-plugin/pr32846c.c
> @@ -0,0 +1,6 @@
> +extern void hash_new (void);
> +void
> +kmod_new (void)
> +{
> +  hash_new();
> +}
> diff --git a/ld/testsuite/ld-plugin/pr32846d.c b/ld/testsuite/ld-plugin/pr32846d.c
> new file mode 100644
> index 00000000000..c6f41021adf
> --- /dev/null
> +++ b/ld/testsuite/ld-plugin/pr32846d.c
> @@ -0,0 +1,12 @@
> +extern void kmod_new (void);
> +extern void mkdir_parents (void);
> +void
> +do_lsmod (void)
> +{
> +  kmod_new ();
> +}
> +void
> +do_static_nodes (void)
> +{
> +  mkdir_parents();
> +}
> diff --git a/ld/testsuite/ld-plugin/pr32846e.c b/ld/testsuite/ld-plugin/pr32846e.c
> new file mode 100644
> index 00000000000..c4e5e56f4f6
> --- /dev/null
> +++ b/ld/testsuite/ld-plugin/pr32846e.c
> @@ -0,0 +1,4 @@
> +void
> +mkdir_p (void)
> +{
> +}
  
Michael Matz April 9, 2025, 12:42 p.m. UTC | #2
Hello,

On Tue, 8 Apr 2025, H.J. Lu wrote:

> commit 2707d55e539ef323dd14a1293e762bf3d9739ee7
> Author: Michael Matz <matz@suse.de>
> Date:   Mon Mar 31 15:57:08 2025 +0200
> 
> skipped the LTO archive member even when the earlier item is also an
> archive.  Instead, skip the LTO archive member only if the earlier item
> is a shared library.

Thanks!  Does it also solve the inline testcase I cobbled up in 
  https://sourceware.org/bugzilla/show_bug.cgi?id=32846#c6
(that wasn't working even without my patch but is related to the 
shared vs. static symbols).


Ciao,
Michael.

> 
> bfd/
> 
> 	PR ld/32846
> 	PR ld/32854
> 	* elflink.c (elf_link_add_archive_symbols): Skip the LTO archive
> 	member only if the earlier item is a shared library.
> 
> ld/
> 
> 	PR ld/32846
> 	PR ld/32854
> 	* testsuite/ld-plugin/lto.exp: Run ld/32846 test.
> 	* testsuite/ld-plugin/pr32846a.c: New file.
> 	* testsuite/ld-plugin/pr32846b.c: Likewise.
> 	* testsuite/ld-plugin/pr32846c.c: Likewise.
> 	* testsuite/ld-plugin/pr32846d.c: Likewise.
> 	* testsuite/ld-plugin/pr32846e.c: Likewise.
> 
> Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
> ---
>  bfd/elflink.c                     |  8 +++++---
>  ld/testsuite/ld-plugin/lto.exp    | 32 +++++++++++++++++++++++++++++++
>  ld/testsuite/ld-plugin/pr32846a.c |  6 ++++++
>  ld/testsuite/ld-plugin/pr32846b.c |  4 ++++
>  ld/testsuite/ld-plugin/pr32846c.c |  6 ++++++
>  ld/testsuite/ld-plugin/pr32846d.c | 12 ++++++++++++
>  ld/testsuite/ld-plugin/pr32846e.c |  4 ++++
>  7 files changed, 69 insertions(+), 3 deletions(-)
>  create mode 100644 ld/testsuite/ld-plugin/pr32846a.c
>  create mode 100644 ld/testsuite/ld-plugin/pr32846b.c
>  create mode 100644 ld/testsuite/ld-plugin/pr32846c.c
>  create mode 100644 ld/testsuite/ld-plugin/pr32846d.c
>  create mode 100644 ld/testsuite/ld-plugin/pr32846e.c
> 
> diff --git a/bfd/elflink.c b/bfd/elflink.c
> index a76e8e38da7..2ac12144990 100644
> --- a/bfd/elflink.c
> +++ b/bfd/elflink.c
> @@ -6290,8 +6290,8 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
>  		    continue;
>  
>  		  /* In the pre-LTO-plugin pass we must not mistakenly
> -		     include this archive member if an earlier BFD
> -		     defined this symbol.  */
> +		     include this archive member if an earlier shared
> +		     library defined this symbol.  */
>  		  struct elf_link_hash_table *htab = elf_hash_table (info);
>  		  if (htab->first_hash)
>  		    {
> @@ -6299,7 +6299,9 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
>  			  = ((struct elf_link_first_hash_entry *)
>  			     bfd_hash_lookup (htab->first_hash, symdef->name,
>  					      false, false));
> -		      if (e && e->abfd != abfd)
> +		      if (e
> +			  && (e->abfd->flags & DYNAMIC) != 0
> +			  && e->abfd != abfd)
>  			continue;
>  		    }
>  		}
> diff --git a/ld/testsuite/ld-plugin/lto.exp b/ld/testsuite/ld-plugin/lto.exp
> index 93491902674..726dd933329 100644
> --- a/ld/testsuite/ld-plugin/lto.exp
> +++ b/ld/testsuite/ld-plugin/lto.exp
> @@ -1212,6 +1212,38 @@ if { [is_elf_format] } {
>  
>  if { [is_elf_format] && [check_lto_shared_available] } {
>      run_ld_link_exec_tests $lto_run_elf_shared_tests
> +    if { [check_lto_fat_available] } {
> +	run_cc_link_tests [list \
> +	    [list \
> +	    	"Build libpr32846a.a" \
> +	    	"$plug_opt" "-O2 -flto $lto_no_fat" \
> +	    	{pr32846a.c pr32846b.c} {} "libpr32846a.a" \
> +	    ] \
> +	    [list \
> +		"Build libpr32846b.a" \
> +	    	"$plug_opt" "-O2 -flto $lto_no_fat" \
> +		{pr32846a.c pr32846b.c pr32846c.c} {} "libpr32846b.a" \
> +	    ] \
> +	    [list \
> +	    	"Build pr32846d.o" \
> +	    	"$plug_opt" "-O2 -flto $lto_no_fat" \
> +	    	{pr32846d.c} {} \
> +	    ] \
> +	    [list \
> +	    	"Build pr32846e.o" \
> +	    	"$plug_opt" "-O2 -flto $lto_no_fat" \
> +	    	{pr32846e.c} {} \
> +	    ] \
> +	    [list \
> +		"Build pr32846" \
> +		"-shared -fPIC -O2 -flto $lto_no_fat -Wl,--no-undefined \
> +		 tmpdir/pr32846d.o tmpdir/libpr32846a.a \
> +		 tmpdir/libpr32846b.a tmpdir/pr32846e.o" \
> +		"-O2 -fPIC -flto $lto_no_fat" \
> +		{dummy.c} {} "pr32846" \
> +	    ] \
> +	] \
> +    }
>  }
>  
>  proc pr20103 {cflags libs} {
> diff --git a/ld/testsuite/ld-plugin/pr32846a.c b/ld/testsuite/ld-plugin/pr32846a.c
> new file mode 100644
> index 00000000000..8c161711bd9
> --- /dev/null
> +++ b/ld/testsuite/ld-plugin/pr32846a.c
> @@ -0,0 +1,6 @@
> +extern void mkdir_p (void);
> +void
> +mkdir_parents (void)
> +{
> +  mkdir_p ();
> +}
> diff --git a/ld/testsuite/ld-plugin/pr32846b.c b/ld/testsuite/ld-plugin/pr32846b.c
> new file mode 100644
> index 00000000000..9776a372d7a
> --- /dev/null
> +++ b/ld/testsuite/ld-plugin/pr32846b.c
> @@ -0,0 +1,4 @@
> +void
> +hash_new (void)
> +{
> +}
> diff --git a/ld/testsuite/ld-plugin/pr32846c.c b/ld/testsuite/ld-plugin/pr32846c.c
> new file mode 100644
> index 00000000000..f87cffb8865
> --- /dev/null
> +++ b/ld/testsuite/ld-plugin/pr32846c.c
> @@ -0,0 +1,6 @@
> +extern void hash_new (void);
> +void
> +kmod_new (void)
> +{
> +  hash_new();
> +}
> diff --git a/ld/testsuite/ld-plugin/pr32846d.c b/ld/testsuite/ld-plugin/pr32846d.c
> new file mode 100644
> index 00000000000..c6f41021adf
> --- /dev/null
> +++ b/ld/testsuite/ld-plugin/pr32846d.c
> @@ -0,0 +1,12 @@
> +extern void kmod_new (void);
> +extern void mkdir_parents (void);
> +void
> +do_lsmod (void)
> +{
> +  kmod_new ();
> +}
> +void
> +do_static_nodes (void)
> +{
> +  mkdir_parents();
> +}
> diff --git a/ld/testsuite/ld-plugin/pr32846e.c b/ld/testsuite/ld-plugin/pr32846e.c
> new file mode 100644
> index 00000000000..c4e5e56f4f6
> --- /dev/null
> +++ b/ld/testsuite/ld-plugin/pr32846e.c
> @@ -0,0 +1,4 @@
> +void
> +mkdir_p (void)
> +{
> +}
>
  
Sam James April 9, 2025, 1 p.m. UTC | #3
Michael Matz <matz@suse.de> writes:

> Hello,
>
> On Tue, 8 Apr 2025, H.J. Lu wrote:
>
>> commit 2707d55e539ef323dd14a1293e762bf3d9739ee7
>> Author: Michael Matz <matz@suse.de>
>> Date:   Mon Mar 31 15:57:08 2025 +0200
>> 
>> skipped the LTO archive member even when the earlier item is also an
>> archive.  Instead, skip the LTO archive member only if the earlier item
>> is a shared library.
>
> Thanks!  Does it also solve the inline testcase I cobbled up in 
>   https://sourceware.org/bugzilla/show_bug.cgi?id=32846#c6
> (that wasn't working even without my patch but is related to the 
> shared vs. static symbols).

That fails still, unfortunately.
  
Michael Matz April 9, 2025, 1:01 p.m. UTC | #4
Hey,

On Wed, 9 Apr 2025, Michael Matz wrote:

> > commit 2707d55e539ef323dd14a1293e762bf3d9739ee7
> > Author: Michael Matz <matz@suse.de>
> > Date:   Mon Mar 31 15:57:08 2025 +0200
> > 
> > skipped the LTO archive member even when the earlier item is also an
> > archive.  Instead, skip the LTO archive member only if the earlier item
> > is a shared library.
> 
> Thanks!  Does it also solve the inline testcase I cobbled up in 
>   https://sourceware.org/bugzilla/show_bug.cgi?id=32846#c6
> (that wasn't working even without my patch but is related to the 
> shared vs. static symbols).

FWIW: It doesn't, it remains resolving to the abort in libc.so, not to 
either the one in the cmdline shared lib (which would also be wrong) nor 
to the one from static.a, which would be the correct one.

Obviously it's still better to have this patch now, as it fixes a 
regression in the wild, but I wonder if adding more and more conditions 
for each testcase we come along is the right approach to deal with this. 
Can you describe what first_hash is _really_ supposed to be and how it 
interacts with the linkers symbol table vs. the two LTO symbol lookup 
phases?


Ciao,
Michael.
  
H.J. Lu April 9, 2025, 2:32 p.m. UTC | #5
On Wed, Apr 9, 2025 at 6:01 AM Michael Matz <matz@suse.de> wrote:
>
> Hey,
>
> On Wed, 9 Apr 2025, Michael Matz wrote:
>
> > > commit 2707d55e539ef323dd14a1293e762bf3d9739ee7
> > > Author: Michael Matz <matz@suse.de>
> > > Date:   Mon Mar 31 15:57:08 2025 +0200
> > >
> > > skipped the LTO archive member even when the earlier item is also an
> > > archive.  Instead, skip the LTO archive member only if the earlier item
> > > is a shared library.
> >
> > Thanks!  Does it also solve the inline testcase I cobbled up in
> >   https://sourceware.org/bugzilla/show_bug.cgi?id=32846#c6
> > (that wasn't working even without my patch but is related to the
> > shared vs. static symbols).
>
> FWIW: It doesn't, it remains resolving to the abort in libc.so, not to
> either the one in the cmdline shared lib (which would also be wrong) nor
> to the one from static.a, which would be the correct one.
>
> Obviously it's still better to have this patch now, as it fixes a
> regression in the wild, but I wonder if adding more and more conditions
> for each testcase we come along is the right approach to deal with this.
> Can you describe what first_hash is _really_ supposed to be and how it
> interacts with the linkers symbol table vs. the two LTO symbol lookup
> phases?
>

first_hash has the first definition for dynamic symbol or archive symbol
lookup.
  
Michael Matz April 9, 2025, 4:36 p.m. UTC | #6
Hello,

On Wed, 9 Apr 2025, H.J. Lu wrote:

> > > Thanks!  Does it also solve the inline testcase I cobbled up in
> > >   https://sourceware.org/bugzilla/show_bug.cgi?id=32846#c6
> > > (that wasn't working even without my patch but is related to the
> > > shared vs. static symbols).
> >
> > FWIW: It doesn't, it remains resolving to the abort in libc.so, not to
> > either the one in the cmdline shared lib (which would also be wrong) nor
> > to the one from static.a, which would be the correct one.
> >
> > Obviously it's still better to have this patch now, as it fixes a
> > regression in the wild, but I wonder if adding more and more conditions
> > for each testcase we come along is the right approach to deal with this.
> > Can you describe what first_hash is _really_ supposed to be and how it
> > interacts with the linkers symbol table vs. the two LTO symbol lookup
> > phases?
> 
> first_hash has the first definition for dynamic symbol or archive symbol
> lookup.

Well, yes, that's how it's currently filled.  But why, and how does that 
interact with the linker symbol table, or rather: how have you designed it 
to interact?  I will also say that the above isn't the full truth, it 
contains the first definition for archive symbols _only_ when at the point 
of seeing it no reference to it existed yet.


Ciao,
Michael.
  
H.J. Lu April 9, 2025, 7:32 p.m. UTC | #7
On Wed, Apr 9, 2025 at 9:36 AM Michael Matz <matz@suse.de> wrote:
>
> Hello,
>
> On Wed, 9 Apr 2025, H.J. Lu wrote:
>
> > > > Thanks!  Does it also solve the inline testcase I cobbled up in
> > > >   https://sourceware.org/bugzilla/show_bug.cgi?id=32846#c6
> > > > (that wasn't working even without my patch but is related to the
> > > > shared vs. static symbols).
> > >
> > > FWIW: It doesn't, it remains resolving to the abort in libc.so, not to
> > > either the one in the cmdline shared lib (which would also be wrong) nor
> > > to the one from static.a, which would be the correct one.
> > >
> > > Obviously it's still better to have this patch now, as it fixes a
> > > regression in the wild, but I wonder if adding more and more conditions
> > > for each testcase we come along is the right approach to deal with this.
> > > Can you describe what first_hash is _really_ supposed to be and how it
> > > interacts with the linkers symbol table vs. the two LTO symbol lookup
> > > phases?
> >
> > first_hash has the first definition for dynamic symbol or archive symbol
> > lookup.
>
> Well, yes, that's how it's currently filled.  But why, and how does that
> interact with the linker symbol table, or rather: how have you designed it
> to interact?  I will also say that the above isn't the full truth, it
> contains the first definition for archive symbols _only_ when at the point
> of seeing it no reference to it existed yet.
>

The design goal is to support shared libraries and archives with LTO.
  
Michael Matz April 10, 2025, 12:30 p.m. UTC | #8
Hello,

On Wed, 9 Apr 2025, H.J. Lu wrote:

> > > > Obviously it's still better to have this patch now, as it fixes a
> > > > regression in the wild, but I wonder if adding more and more conditions
> > > > for each testcase we come along is the right approach to deal with this.
> > > > Can you describe what first_hash is _really_ supposed to be and how it
> > > > interacts with the linkers symbol table vs. the two LTO symbol lookup
> > > > phases?
> > >
> > > first_hash has the first definition for dynamic symbol or archive symbol
> > > lookup.
> >
> > Well, yes, that's how it's currently filled.  But why, and how does that
> > interact with the linker symbol table, or rather: how have you designed it
> > to interact?  I will also say that the above isn't the full truth, it
> > contains the first definition for archive symbols _only_ when at the point
> > of seeing it no reference to it existed yet.
> >
> 
> The design goal is to support shared libraries and archives with LTO.

Thanks for stating the obvious.  I haven't asked for the design goal, but 
the design, i.e. how that goal is intended to be achieved.  Though, I'm 
now sorry to have asked that.


Ciao,
Michael.
  
H.J. Lu April 10, 2025, 2:39 p.m. UTC | #9
On Tue, Apr 8, 2025 at 9:52 PM Sam James <sam@gentoo.org> wrote:
>
> "H.J. Lu" <hjl.tools@gmail.com> writes:
>
> > commit 2707d55e539ef323dd14a1293e762bf3d9739ee7
> > Author: Michael Matz <matz@suse.de>
> > Date:   Mon Mar 31 15:57:08 2025 +0200
> >
> > skipped the LTO archive member even when the earlier item is also an
> > archive.  Instead, skip the LTO archive member only if the earlier item
> > is a shared library.
>
> Thanks. kmod now works, I'll test others for the next day or so.

Any update on testing?

> >
> > bfd/
> >
> >       PR ld/32846
> >       PR ld/32854
> >       * elflink.c (elf_link_add_archive_symbols): Skip the LTO archive
> >       member only if the earlier item is a shared library.
> >
> > ld/
> >
> >       PR ld/32846
> >       PR ld/32854
> >       * testsuite/ld-plugin/lto.exp: Run ld/32846 test.
> >       * testsuite/ld-plugin/pr32846a.c: New file.
> >       * testsuite/ld-plugin/pr32846b.c: Likewise.
> >       * testsuite/ld-plugin/pr32846c.c: Likewise.
> >       * testsuite/ld-plugin/pr32846d.c: Likewise.
> >       * testsuite/ld-plugin/pr32846e.c: Likewise.
> >
> > Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
> > ---
> >  bfd/elflink.c                     |  8 +++++---
> >  ld/testsuite/ld-plugin/lto.exp    | 32 +++++++++++++++++++++++++++++++
> >  ld/testsuite/ld-plugin/pr32846a.c |  6 ++++++
> >  ld/testsuite/ld-plugin/pr32846b.c |  4 ++++
> >  ld/testsuite/ld-plugin/pr32846c.c |  6 ++++++
> >  ld/testsuite/ld-plugin/pr32846d.c | 12 ++++++++++++
> >  ld/testsuite/ld-plugin/pr32846e.c |  4 ++++
> >  7 files changed, 69 insertions(+), 3 deletions(-)
> >  create mode 100644 ld/testsuite/ld-plugin/pr32846a.c
> >  create mode 100644 ld/testsuite/ld-plugin/pr32846b.c
> >  create mode 100644 ld/testsuite/ld-plugin/pr32846c.c
> >  create mode 100644 ld/testsuite/ld-plugin/pr32846d.c
> >  create mode 100644 ld/testsuite/ld-plugin/pr32846e.c
> >
> > diff --git a/bfd/elflink.c b/bfd/elflink.c
> > index a76e8e38da7..2ac12144990 100644
> > --- a/bfd/elflink.c
> > +++ b/bfd/elflink.c
> > @@ -6290,8 +6290,8 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
> >                   continue;
> >
> >                 /* In the pre-LTO-plugin pass we must not mistakenly
> > -                  include this archive member if an earlier BFD
> > -                  defined this symbol.  */
> > +                  include this archive member if an earlier shared
> > +                  library defined this symbol.  */
> >                 struct elf_link_hash_table *htab = elf_hash_table (info);
> >                 if (htab->first_hash)
> >                   {
> > @@ -6299,7 +6299,9 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
> >                         = ((struct elf_link_first_hash_entry *)
> >                            bfd_hash_lookup (htab->first_hash, symdef->name,
> >                                             false, false));
> > -                   if (e && e->abfd != abfd)
> > +                   if (e
> > +                       && (e->abfd->flags & DYNAMIC) != 0
> > +                       && e->abfd != abfd)
> >                       continue;
> >                   }
> >               }
> > diff --git a/ld/testsuite/ld-plugin/lto.exp b/ld/testsuite/ld-plugin/lto.exp
> > index 93491902674..726dd933329 100644
> > --- a/ld/testsuite/ld-plugin/lto.exp
> > +++ b/ld/testsuite/ld-plugin/lto.exp
> > @@ -1212,6 +1212,38 @@ if { [is_elf_format] } {
> >
> >  if { [is_elf_format] && [check_lto_shared_available] } {
> >      run_ld_link_exec_tests $lto_run_elf_shared_tests
> > +    if { [check_lto_fat_available] } {
> > +     run_cc_link_tests [list \
> > +         [list \
> > +             "Build libpr32846a.a" \
> > +             "$plug_opt" "-O2 -flto $lto_no_fat" \
> > +             {pr32846a.c pr32846b.c} {} "libpr32846a.a" \
> > +         ] \
> > +         [list \
> > +             "Build libpr32846b.a" \
> > +             "$plug_opt" "-O2 -flto $lto_no_fat" \
> > +             {pr32846a.c pr32846b.c pr32846c.c} {} "libpr32846b.a" \
> > +         ] \
> > +         [list \
> > +             "Build pr32846d.o" \
> > +             "$plug_opt" "-O2 -flto $lto_no_fat" \
> > +             {pr32846d.c} {} \
> > +         ] \
> > +         [list \
> > +             "Build pr32846e.o" \
> > +             "$plug_opt" "-O2 -flto $lto_no_fat" \
> > +             {pr32846e.c} {} \
> > +         ] \
> > +         [list \
> > +             "Build pr32846" \
> > +             "-shared -fPIC -O2 -flto $lto_no_fat -Wl,--no-undefined \
> > +              tmpdir/pr32846d.o tmpdir/libpr32846a.a \
> > +              tmpdir/libpr32846b.a tmpdir/pr32846e.o" \
> > +             "-O2 -fPIC -flto $lto_no_fat" \
> > +             {dummy.c} {} "pr32846" \
> > +         ] \
> > +     ] \
> > +    }
> >  }
> >
> >  proc pr20103 {cflags libs} {
> > diff --git a/ld/testsuite/ld-plugin/pr32846a.c b/ld/testsuite/ld-plugin/pr32846a.c
> > new file mode 100644
> > index 00000000000..8c161711bd9
> > --- /dev/null
> > +++ b/ld/testsuite/ld-plugin/pr32846a.c
> > @@ -0,0 +1,6 @@
> > +extern void mkdir_p (void);
> > +void
> > +mkdir_parents (void)
> > +{
> > +  mkdir_p ();
> > +}
> > diff --git a/ld/testsuite/ld-plugin/pr32846b.c b/ld/testsuite/ld-plugin/pr32846b.c
> > new file mode 100644
> > index 00000000000..9776a372d7a
> > --- /dev/null
> > +++ b/ld/testsuite/ld-plugin/pr32846b.c
> > @@ -0,0 +1,4 @@
> > +void
> > +hash_new (void)
> > +{
> > +}
> > diff --git a/ld/testsuite/ld-plugin/pr32846c.c b/ld/testsuite/ld-plugin/pr32846c.c
> > new file mode 100644
> > index 00000000000..f87cffb8865
> > --- /dev/null
> > +++ b/ld/testsuite/ld-plugin/pr32846c.c
> > @@ -0,0 +1,6 @@
> > +extern void hash_new (void);
> > +void
> > +kmod_new (void)
> > +{
> > +  hash_new();
> > +}
> > diff --git a/ld/testsuite/ld-plugin/pr32846d.c b/ld/testsuite/ld-plugin/pr32846d.c
> > new file mode 100644
> > index 00000000000..c6f41021adf
> > --- /dev/null
> > +++ b/ld/testsuite/ld-plugin/pr32846d.c
> > @@ -0,0 +1,12 @@
> > +extern void kmod_new (void);
> > +extern void mkdir_parents (void);
> > +void
> > +do_lsmod (void)
> > +{
> > +  kmod_new ();
> > +}
> > +void
> > +do_static_nodes (void)
> > +{
> > +  mkdir_parents();
> > +}
> > diff --git a/ld/testsuite/ld-plugin/pr32846e.c b/ld/testsuite/ld-plugin/pr32846e.c
> > new file mode 100644
> > index 00000000000..c4e5e56f4f6
> > --- /dev/null
> > +++ b/ld/testsuite/ld-plugin/pr32846e.c
> > @@ -0,0 +1,4 @@
> > +void
> > +mkdir_p (void)
> > +{
> > +}
  
Sam James April 10, 2025, 4:05 p.m. UTC | #10
"H.J. Lu" <hjl.tools@gmail.com> writes:

> On Tue, Apr 8, 2025 at 9:52 PM Sam James <sam@gentoo.org> wrote:
>>
>> "H.J. Lu" <hjl.tools@gmail.com> writes:
>>
>> > commit 2707d55e539ef323dd14a1293e762bf3d9739ee7
>> > Author: Michael Matz <matz@suse.de>
>> > Date:   Mon Mar 31 15:57:08 2025 +0200
>> >
>> > skipped the LTO archive member even when the earlier item is also an
>> > archive.  Instead, skip the LTO archive member only if the earlier item
>> > is a shared library.
>>
>> Thanks. kmod now works, I'll test others for the next day or so.
>
> Any update on testing?

I think it looks good. No problems.

>
>> >
>> > bfd/
>> >
>> >       PR ld/32846
>> >       PR ld/32854
>> >       * elflink.c (elf_link_add_archive_symbols): Skip the LTO archive
>> >       member only if the earlier item is a shared library.
>> >
>> > ld/
>> >
>> >       PR ld/32846
>> >       PR ld/32854
>> >       * testsuite/ld-plugin/lto.exp: Run ld/32846 test.
>> >       * testsuite/ld-plugin/pr32846a.c: New file.
>> >       * testsuite/ld-plugin/pr32846b.c: Likewise.
>> >       * testsuite/ld-plugin/pr32846c.c: Likewise.
>> >       * testsuite/ld-plugin/pr32846d.c: Likewise.
>> >       * testsuite/ld-plugin/pr32846e.c: Likewise.
>> >
>> > Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
>> > ---
>> >  bfd/elflink.c                     |  8 +++++---
>> >  ld/testsuite/ld-plugin/lto.exp    | 32 +++++++++++++++++++++++++++++++
>> >  ld/testsuite/ld-plugin/pr32846a.c |  6 ++++++
>> >  ld/testsuite/ld-plugin/pr32846b.c |  4 ++++
>> >  ld/testsuite/ld-plugin/pr32846c.c |  6 ++++++
>> >  ld/testsuite/ld-plugin/pr32846d.c | 12 ++++++++++++
>> >  ld/testsuite/ld-plugin/pr32846e.c |  4 ++++
>> >  7 files changed, 69 insertions(+), 3 deletions(-)
>> >  create mode 100644 ld/testsuite/ld-plugin/pr32846a.c
>> >  create mode 100644 ld/testsuite/ld-plugin/pr32846b.c
>> >  create mode 100644 ld/testsuite/ld-plugin/pr32846c.c
>> >  create mode 100644 ld/testsuite/ld-plugin/pr32846d.c
>> >  create mode 100644 ld/testsuite/ld-plugin/pr32846e.c
>> >
>> > diff --git a/bfd/elflink.c b/bfd/elflink.c
>> > index a76e8e38da7..2ac12144990 100644
>> > --- a/bfd/elflink.c
>> > +++ b/bfd/elflink.c
>> > @@ -6290,8 +6290,8 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
>> >                   continue;
>> >
>> >                 /* In the pre-LTO-plugin pass we must not mistakenly
>> > -                  include this archive member if an earlier BFD
>> > -                  defined this symbol.  */
>> > +                  include this archive member if an earlier shared
>> > +                  library defined this symbol.  */
>> >                 struct elf_link_hash_table *htab = elf_hash_table (info);
>> >                 if (htab->first_hash)
>> >                   {
>> > @@ -6299,7 +6299,9 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
>> >                         = ((struct elf_link_first_hash_entry *)
>> >                            bfd_hash_lookup (htab->first_hash, symdef->name,
>> >                                             false, false));
>> > -                   if (e && e->abfd != abfd)
>> > +                   if (e
>> > +                       && (e->abfd->flags & DYNAMIC) != 0
>> > +                       && e->abfd != abfd)
>> >                       continue;
>> >                   }
>> >               }
>> > diff --git a/ld/testsuite/ld-plugin/lto.exp b/ld/testsuite/ld-plugin/lto.exp
>> > index 93491902674..726dd933329 100644
>> > --- a/ld/testsuite/ld-plugin/lto.exp
>> > +++ b/ld/testsuite/ld-plugin/lto.exp
>> > @@ -1212,6 +1212,38 @@ if { [is_elf_format] } {
>> >
>> >  if { [is_elf_format] && [check_lto_shared_available] } {
>> >      run_ld_link_exec_tests $lto_run_elf_shared_tests
>> > +    if { [check_lto_fat_available] } {
>> > +     run_cc_link_tests [list \
>> > +         [list \
>> > +             "Build libpr32846a.a" \
>> > +             "$plug_opt" "-O2 -flto $lto_no_fat" \
>> > +             {pr32846a.c pr32846b.c} {} "libpr32846a.a" \
>> > +         ] \
>> > +         [list \
>> > +             "Build libpr32846b.a" \
>> > +             "$plug_opt" "-O2 -flto $lto_no_fat" \
>> > +             {pr32846a.c pr32846b.c pr32846c.c} {} "libpr32846b.a" \
>> > +         ] \
>> > +         [list \
>> > +             "Build pr32846d.o" \
>> > +             "$plug_opt" "-O2 -flto $lto_no_fat" \
>> > +             {pr32846d.c} {} \
>> > +         ] \
>> > +         [list \
>> > +             "Build pr32846e.o" \
>> > +             "$plug_opt" "-O2 -flto $lto_no_fat" \
>> > +             {pr32846e.c} {} \
>> > +         ] \
>> > +         [list \
>> > +             "Build pr32846" \
>> > +             "-shared -fPIC -O2 -flto $lto_no_fat -Wl,--no-undefined \
>> > +              tmpdir/pr32846d.o tmpdir/libpr32846a.a \
>> > +              tmpdir/libpr32846b.a tmpdir/pr32846e.o" \
>> > +             "-O2 -fPIC -flto $lto_no_fat" \
>> > +             {dummy.c} {} "pr32846" \
>> > +         ] \
>> > +     ] \
>> > +    }
>> >  }
>> >
>> >  proc pr20103 {cflags libs} {
>> > diff --git a/ld/testsuite/ld-plugin/pr32846a.c b/ld/testsuite/ld-plugin/pr32846a.c
>> > new file mode 100644
>> > index 00000000000..8c161711bd9
>> > --- /dev/null
>> > +++ b/ld/testsuite/ld-plugin/pr32846a.c
>> > @@ -0,0 +1,6 @@
>> > +extern void mkdir_p (void);
>> > +void
>> > +mkdir_parents (void)
>> > +{
>> > +  mkdir_p ();
>> > +}
>> > diff --git a/ld/testsuite/ld-plugin/pr32846b.c b/ld/testsuite/ld-plugin/pr32846b.c
>> > new file mode 100644
>> > index 00000000000..9776a372d7a
>> > --- /dev/null
>> > +++ b/ld/testsuite/ld-plugin/pr32846b.c
>> > @@ -0,0 +1,4 @@
>> > +void
>> > +hash_new (void)
>> > +{
>> > +}
>> > diff --git a/ld/testsuite/ld-plugin/pr32846c.c b/ld/testsuite/ld-plugin/pr32846c.c
>> > new file mode 100644
>> > index 00000000000..f87cffb8865
>> > --- /dev/null
>> > +++ b/ld/testsuite/ld-plugin/pr32846c.c
>> > @@ -0,0 +1,6 @@
>> > +extern void hash_new (void);
>> > +void
>> > +kmod_new (void)
>> > +{
>> > +  hash_new();
>> > +}
>> > diff --git a/ld/testsuite/ld-plugin/pr32846d.c b/ld/testsuite/ld-plugin/pr32846d.c
>> > new file mode 100644
>> > index 00000000000..c6f41021adf
>> > --- /dev/null
>> > +++ b/ld/testsuite/ld-plugin/pr32846d.c
>> > @@ -0,0 +1,12 @@
>> > +extern void kmod_new (void);
>> > +extern void mkdir_parents (void);
>> > +void
>> > +do_lsmod (void)
>> > +{
>> > +  kmod_new ();
>> > +}
>> > +void
>> > +do_static_nodes (void)
>> > +{
>> > +  mkdir_parents();
>> > +}
>> > diff --git a/ld/testsuite/ld-plugin/pr32846e.c b/ld/testsuite/ld-plugin/pr32846e.c
>> > new file mode 100644
>> > index 00000000000..c4e5e56f4f6
>> > --- /dev/null
>> > +++ b/ld/testsuite/ld-plugin/pr32846e.c
>> > @@ -0,0 +1,4 @@
>> > +void
>> > +mkdir_p (void)
>> > +{
>> > +}
  
H.J. Lu April 10, 2025, 5:28 p.m. UTC | #11
On Thu, Apr 10, 2025 at 9:05 AM Sam James <sam@gentoo.org> wrote:
>
> "H.J. Lu" <hjl.tools@gmail.com> writes:
>
> > On Tue, Apr 8, 2025 at 9:52 PM Sam James <sam@gentoo.org> wrote:
> >>
> >> "H.J. Lu" <hjl.tools@gmail.com> writes:
> >>
> >> > commit 2707d55e539ef323dd14a1293e762bf3d9739ee7
> >> > Author: Michael Matz <matz@suse.de>
> >> > Date:   Mon Mar 31 15:57:08 2025 +0200
> >> >
> >> > skipped the LTO archive member even when the earlier item is also an
> >> > archive.  Instead, skip the LTO archive member only if the earlier item
> >> > is a shared library.
> >>
> >> Thanks. kmod now works, I'll test others for the next day or so.
> >
> > Any update on testing?
>
> I think it looks good. No problems.

I am checking it in.

Thanks.

> >
> >> >
> >> > bfd/
> >> >
> >> >       PR ld/32846
> >> >       PR ld/32854
> >> >       * elflink.c (elf_link_add_archive_symbols): Skip the LTO archive
> >> >       member only if the earlier item is a shared library.
> >> >
> >> > ld/
> >> >
> >> >       PR ld/32846
> >> >       PR ld/32854
> >> >       * testsuite/ld-plugin/lto.exp: Run ld/32846 test.
> >> >       * testsuite/ld-plugin/pr32846a.c: New file.
> >> >       * testsuite/ld-plugin/pr32846b.c: Likewise.
> >> >       * testsuite/ld-plugin/pr32846c.c: Likewise.
> >> >       * testsuite/ld-plugin/pr32846d.c: Likewise.
> >> >       * testsuite/ld-plugin/pr32846e.c: Likewise.
> >> >
> >> > Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
> >> > ---
> >> >  bfd/elflink.c                     |  8 +++++---
> >> >  ld/testsuite/ld-plugin/lto.exp    | 32 +++++++++++++++++++++++++++++++
> >> >  ld/testsuite/ld-plugin/pr32846a.c |  6 ++++++
> >> >  ld/testsuite/ld-plugin/pr32846b.c |  4 ++++
> >> >  ld/testsuite/ld-plugin/pr32846c.c |  6 ++++++
> >> >  ld/testsuite/ld-plugin/pr32846d.c | 12 ++++++++++++
> >> >  ld/testsuite/ld-plugin/pr32846e.c |  4 ++++
> >> >  7 files changed, 69 insertions(+), 3 deletions(-)
> >> >  create mode 100644 ld/testsuite/ld-plugin/pr32846a.c
> >> >  create mode 100644 ld/testsuite/ld-plugin/pr32846b.c
> >> >  create mode 100644 ld/testsuite/ld-plugin/pr32846c.c
> >> >  create mode 100644 ld/testsuite/ld-plugin/pr32846d.c
> >> >  create mode 100644 ld/testsuite/ld-plugin/pr32846e.c
> >> >
> >> > diff --git a/bfd/elflink.c b/bfd/elflink.c
> >> > index a76e8e38da7..2ac12144990 100644
> >> > --- a/bfd/elflink.c
> >> > +++ b/bfd/elflink.c
> >> > @@ -6290,8 +6290,8 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
> >> >                   continue;
> >> >
> >> >                 /* In the pre-LTO-plugin pass we must not mistakenly
> >> > -                  include this archive member if an earlier BFD
> >> > -                  defined this symbol.  */
> >> > +                  include this archive member if an earlier shared
> >> > +                  library defined this symbol.  */
> >> >                 struct elf_link_hash_table *htab = elf_hash_table (info);
> >> >                 if (htab->first_hash)
> >> >                   {
> >> > @@ -6299,7 +6299,9 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
> >> >                         = ((struct elf_link_first_hash_entry *)
> >> >                            bfd_hash_lookup (htab->first_hash, symdef->name,
> >> >                                             false, false));
> >> > -                   if (e && e->abfd != abfd)
> >> > +                   if (e
> >> > +                       && (e->abfd->flags & DYNAMIC) != 0
> >> > +                       && e->abfd != abfd)
> >> >                       continue;
> >> >                   }
> >> >               }
> >> > diff --git a/ld/testsuite/ld-plugin/lto.exp b/ld/testsuite/ld-plugin/lto.exp
> >> > index 93491902674..726dd933329 100644
> >> > --- a/ld/testsuite/ld-plugin/lto.exp
> >> > +++ b/ld/testsuite/ld-plugin/lto.exp
> >> > @@ -1212,6 +1212,38 @@ if { [is_elf_format] } {
> >> >
> >> >  if { [is_elf_format] && [check_lto_shared_available] } {
> >> >      run_ld_link_exec_tests $lto_run_elf_shared_tests
> >> > +    if { [check_lto_fat_available] } {
> >> > +     run_cc_link_tests [list \
> >> > +         [list \
> >> > +             "Build libpr32846a.a" \
> >> > +             "$plug_opt" "-O2 -flto $lto_no_fat" \
> >> > +             {pr32846a.c pr32846b.c} {} "libpr32846a.a" \
> >> > +         ] \
> >> > +         [list \
> >> > +             "Build libpr32846b.a" \
> >> > +             "$plug_opt" "-O2 -flto $lto_no_fat" \
> >> > +             {pr32846a.c pr32846b.c pr32846c.c} {} "libpr32846b.a" \
> >> > +         ] \
> >> > +         [list \
> >> > +             "Build pr32846d.o" \
> >> > +             "$plug_opt" "-O2 -flto $lto_no_fat" \
> >> > +             {pr32846d.c} {} \
> >> > +         ] \
> >> > +         [list \
> >> > +             "Build pr32846e.o" \
> >> > +             "$plug_opt" "-O2 -flto $lto_no_fat" \
> >> > +             {pr32846e.c} {} \
> >> > +         ] \
> >> > +         [list \
> >> > +             "Build pr32846" \
> >> > +             "-shared -fPIC -O2 -flto $lto_no_fat -Wl,--no-undefined \
> >> > +              tmpdir/pr32846d.o tmpdir/libpr32846a.a \
> >> > +              tmpdir/libpr32846b.a tmpdir/pr32846e.o" \
> >> > +             "-O2 -fPIC -flto $lto_no_fat" \
> >> > +             {dummy.c} {} "pr32846" \
> >> > +         ] \
> >> > +     ] \
> >> > +    }
> >> >  }
> >> >
> >> >  proc pr20103 {cflags libs} {
> >> > diff --git a/ld/testsuite/ld-plugin/pr32846a.c b/ld/testsuite/ld-plugin/pr32846a.c
> >> > new file mode 100644
> >> > index 00000000000..8c161711bd9
> >> > --- /dev/null
> >> > +++ b/ld/testsuite/ld-plugin/pr32846a.c
> >> > @@ -0,0 +1,6 @@
> >> > +extern void mkdir_p (void);
> >> > +void
> >> > +mkdir_parents (void)
> >> > +{
> >> > +  mkdir_p ();
> >> > +}
> >> > diff --git a/ld/testsuite/ld-plugin/pr32846b.c b/ld/testsuite/ld-plugin/pr32846b.c
> >> > new file mode 100644
> >> > index 00000000000..9776a372d7a
> >> > --- /dev/null
> >> > +++ b/ld/testsuite/ld-plugin/pr32846b.c
> >> > @@ -0,0 +1,4 @@
> >> > +void
> >> > +hash_new (void)
> >> > +{
> >> > +}
> >> > diff --git a/ld/testsuite/ld-plugin/pr32846c.c b/ld/testsuite/ld-plugin/pr32846c.c
> >> > new file mode 100644
> >> > index 00000000000..f87cffb8865
> >> > --- /dev/null
> >> > +++ b/ld/testsuite/ld-plugin/pr32846c.c
> >> > @@ -0,0 +1,6 @@
> >> > +extern void hash_new (void);
> >> > +void
> >> > +kmod_new (void)
> >> > +{
> >> > +  hash_new();
> >> > +}
> >> > diff --git a/ld/testsuite/ld-plugin/pr32846d.c b/ld/testsuite/ld-plugin/pr32846d.c
> >> > new file mode 100644
> >> > index 00000000000..c6f41021adf
> >> > --- /dev/null
> >> > +++ b/ld/testsuite/ld-plugin/pr32846d.c
> >> > @@ -0,0 +1,12 @@
> >> > +extern void kmod_new (void);
> >> > +extern void mkdir_parents (void);
> >> > +void
> >> > +do_lsmod (void)
> >> > +{
> >> > +  kmod_new ();
> >> > +}
> >> > +void
> >> > +do_static_nodes (void)
> >> > +{
> >> > +  mkdir_parents();
> >> > +}
> >> > diff --git a/ld/testsuite/ld-plugin/pr32846e.c b/ld/testsuite/ld-plugin/pr32846e.c
> >> > new file mode 100644
> >> > index 00000000000..c4e5e56f4f6
> >> > --- /dev/null
> >> > +++ b/ld/testsuite/ld-plugin/pr32846e.c
> >> > @@ -0,0 +1,4 @@
> >> > +void
> >> > +mkdir_p (void)
> >> > +{
> >> > +}
  

Patch

diff --git a/bfd/elflink.c b/bfd/elflink.c
index a76e8e38da7..2ac12144990 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -6290,8 +6290,8 @@  elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
 		    continue;
 
 		  /* In the pre-LTO-plugin pass we must not mistakenly
-		     include this archive member if an earlier BFD
-		     defined this symbol.  */
+		     include this archive member if an earlier shared
+		     library defined this symbol.  */
 		  struct elf_link_hash_table *htab = elf_hash_table (info);
 		  if (htab->first_hash)
 		    {
@@ -6299,7 +6299,9 @@  elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
 			  = ((struct elf_link_first_hash_entry *)
 			     bfd_hash_lookup (htab->first_hash, symdef->name,
 					      false, false));
-		      if (e && e->abfd != abfd)
+		      if (e
+			  && (e->abfd->flags & DYNAMIC) != 0
+			  && e->abfd != abfd)
 			continue;
 		    }
 		}
diff --git a/ld/testsuite/ld-plugin/lto.exp b/ld/testsuite/ld-plugin/lto.exp
index 93491902674..726dd933329 100644
--- a/ld/testsuite/ld-plugin/lto.exp
+++ b/ld/testsuite/ld-plugin/lto.exp
@@ -1212,6 +1212,38 @@  if { [is_elf_format] } {
 
 if { [is_elf_format] && [check_lto_shared_available] } {
     run_ld_link_exec_tests $lto_run_elf_shared_tests
+    if { [check_lto_fat_available] } {
+	run_cc_link_tests [list \
+	    [list \
+	    	"Build libpr32846a.a" \
+	    	"$plug_opt" "-O2 -flto $lto_no_fat" \
+	    	{pr32846a.c pr32846b.c} {} "libpr32846a.a" \
+	    ] \
+	    [list \
+		"Build libpr32846b.a" \
+	    	"$plug_opt" "-O2 -flto $lto_no_fat" \
+		{pr32846a.c pr32846b.c pr32846c.c} {} "libpr32846b.a" \
+	    ] \
+	    [list \
+	    	"Build pr32846d.o" \
+	    	"$plug_opt" "-O2 -flto $lto_no_fat" \
+	    	{pr32846d.c} {} \
+	    ] \
+	    [list \
+	    	"Build pr32846e.o" \
+	    	"$plug_opt" "-O2 -flto $lto_no_fat" \
+	    	{pr32846e.c} {} \
+	    ] \
+	    [list \
+		"Build pr32846" \
+		"-shared -fPIC -O2 -flto $lto_no_fat -Wl,--no-undefined \
+		 tmpdir/pr32846d.o tmpdir/libpr32846a.a \
+		 tmpdir/libpr32846b.a tmpdir/pr32846e.o" \
+		"-O2 -fPIC -flto $lto_no_fat" \
+		{dummy.c} {} "pr32846" \
+	    ] \
+	] \
+    }
 }
 
 proc pr20103 {cflags libs} {
diff --git a/ld/testsuite/ld-plugin/pr32846a.c b/ld/testsuite/ld-plugin/pr32846a.c
new file mode 100644
index 00000000000..8c161711bd9
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr32846a.c
@@ -0,0 +1,6 @@ 
+extern void mkdir_p (void);
+void
+mkdir_parents (void)
+{
+  mkdir_p ();
+}
diff --git a/ld/testsuite/ld-plugin/pr32846b.c b/ld/testsuite/ld-plugin/pr32846b.c
new file mode 100644
index 00000000000..9776a372d7a
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr32846b.c
@@ -0,0 +1,4 @@ 
+void
+hash_new (void)
+{
+}
diff --git a/ld/testsuite/ld-plugin/pr32846c.c b/ld/testsuite/ld-plugin/pr32846c.c
new file mode 100644
index 00000000000..f87cffb8865
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr32846c.c
@@ -0,0 +1,6 @@ 
+extern void hash_new (void);
+void
+kmod_new (void)
+{
+  hash_new();
+}
diff --git a/ld/testsuite/ld-plugin/pr32846d.c b/ld/testsuite/ld-plugin/pr32846d.c
new file mode 100644
index 00000000000..c6f41021adf
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr32846d.c
@@ -0,0 +1,12 @@ 
+extern void kmod_new (void);
+extern void mkdir_parents (void);
+void
+do_lsmod (void)
+{
+  kmod_new ();
+}
+void
+do_static_nodes (void)
+{
+  mkdir_parents();
+}
diff --git a/ld/testsuite/ld-plugin/pr32846e.c b/ld/testsuite/ld-plugin/pr32846e.c
new file mode 100644
index 00000000000..c4e5e56f4f6
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr32846e.c
@@ -0,0 +1,4 @@ 
+void
+mkdir_p (void)
+{
+}