[v2] gold: Always resolve hidden weak undefined in PIE to 0

Message ID 20240817141453.2887750-1-hjl.tools@gmail.com
State Superseded
Headers
Series [v2] gold: Always resolve hidden weak undefined in PIE to 0 |

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-aarch64 success Test passed
linaro-tcwg-bot/tcwg_binutils_check--master-arm success Test passed

Commit Message

H.J. Lu Aug. 17, 2024, 2:14 p.m. UTC
  Hidden weak undefined symbol in PIE should be resolved to 0.

	PR gold/32071
	* symtab.cc (Symbol::final_value_is_known): Always resolve hidden
	weak undefined in PIE to 0.
	* testsuite/Makefile.am: Add the hidden_weak_undef test.
	* testsuite/Makefile.in: Regenerated.
	* testsuite/hidden_weak_undef.c: New file.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
---
 gold/symtab.cc                     | 10 +++++-
 gold/testsuite/Makefile.am         |  5 +++
 gold/testsuite/Makefile.in         | 50 +++++++++++++++++++++++++-----
 gold/testsuite/hidden_weak_undef.c | 35 +++++++++++++++++++++
 4 files changed, 92 insertions(+), 8 deletions(-)
 create mode 100644 gold/testsuite/hidden_weak_undef.c
  

Comments

H.J. Lu Aug. 20, 2024, 2:18 p.m. UTC | #1
On Sat, Aug 17, 2024 at 7:14 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> Hidden weak undefined symbol in PIE should be resolved to 0.
>
>         PR gold/32071
>         * symtab.cc (Symbol::final_value_is_known): Always resolve hidden
>         weak undefined in PIE to 0.
>         * testsuite/Makefile.am: Add the hidden_weak_undef test.
>         * testsuite/Makefile.in: Regenerated.
>         * testsuite/hidden_weak_undef.c: New file.
>
> Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
> ---
>  gold/symtab.cc                     | 10 +++++-
>  gold/testsuite/Makefile.am         |  5 +++
>  gold/testsuite/Makefile.in         | 50 +++++++++++++++++++++++++-----
>  gold/testsuite/hidden_weak_undef.c | 35 +++++++++++++++++++++
>  4 files changed, 92 insertions(+), 8 deletions(-)
>  create mode 100644 gold/testsuite/hidden_weak_undef.c
>
> diff --git a/gold/symtab.cc b/gold/symtab.cc
> index 5857dd7b098..5d7f4d47775 100644
> --- a/gold/symtab.cc
> +++ b/gold/symtab.cc
> @@ -450,7 +450,15 @@ Symbol::final_value_is_known() const
>         || parameters->options().relocatable())
>        && !(this->type() == elfcpp::STT_TLS
>             && parameters->options().pie()))
> -    return false;
> +    {
> +      // Hidden weak undefined in PIE is always resolved to 0.
> +      if (this->visibility() == elfcpp::STV_HIDDEN
> +         && this->is_weak_undefined()
> +         && parameters->options().pie())
> +       return true;
> +
> +      return false;
> +    }
>
>    // If the symbol is not from an object file, and is not undefined,
>    // then it is defined, and known.
> diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am
> index a40f7624395..65d16ba393d 100644
> --- a/gold/testsuite/Makefile.am
> +++ b/gold/testsuite/Makefile.am
> @@ -4531,3 +4531,8 @@ package_metadata_test.o: package_metadata_main.c
>  package_metadata_test$(EXEEXT): package_metadata_test.o gcctestdir/ld
>         $(CXXLINK) package_metadata_test.o -Wl,--package-metadata='{"foo":"bar"}'
>         $(TEST_READELF) --notes $@ | grep -q '{"foo":"bar"}'
> +
> +check_PROGRAMS += hidden_weak_undef
> +hidden_weak_undef_SOURCES = hidden_weak_undef.c
> +hidden_weak_undef_CFLAGS = -fPIE
> +hidden_weak_undef_LDFLAGS = -pie
> diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in
> index 78ca73acb17..a676a88f7f2 100644
> --- a/gold/testsuite/Makefile.in
> +++ b/gold/testsuite/Makefile.in
> @@ -110,7 +110,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
>         $(am__EXEEXT_40) $(am__EXEEXT_41) $(am__EXEEXT_42) \
>         $(am__EXEEXT_43) $(am__EXEEXT_44) $(am__EXEEXT_45) \
>         $(am__EXEEXT_46) $(am__EXEEXT_47) $(am__EXEEXT_48) \
> -       package_metadata_test$(EXEEXT)
> +       package_metadata_test$(EXEEXT) hidden_weak_undef$(EXEEXT)
>  @NATIVE_OR_CROSS_LINKER_TRUE@am__append_1 = object_unittest \
>  @NATIVE_OR_CROSS_LINKER_TRUE@  binary_unittest leb128_unittest \
>  @NATIVE_OR_CROSS_LINKER_TRUE@  overflow_unittest
> @@ -1598,6 +1598,12 @@ flagstest_o_specialfile_and_compress_debug_sections_LDADD = $(LDADD)
>  flagstest_o_ttext_1_SOURCES = flagstest_o_ttext_1.c
>  flagstest_o_ttext_1_OBJECTS = flagstest_o_ttext_1.$(OBJEXT)
>  flagstest_o_ttext_1_LDADD = $(LDADD)
> +am_hidden_weak_undef_OBJECTS =  \
> +       hidden_weak_undef-hidden_weak_undef.$(OBJEXT)
> +hidden_weak_undef_OBJECTS = $(am_hidden_weak_undef_OBJECTS)
> +hidden_weak_undef_LDADD = $(LDADD)
> +hidden_weak_undef_LINK = $(CCLD) $(hidden_weak_undef_CFLAGS) $(CFLAGS) \
> +       $(hidden_weak_undef_LDFLAGS) $(LDFLAGS) -o $@
>  icf_virtual_function_folding_test_SOURCES =  \
>         icf_virtual_function_folding_test.c
>  icf_virtual_function_folding_test_OBJECTS =  \
> @@ -2340,12 +2346,13 @@ SOURCES = $(libgoldtest_a_SOURCES) $(aarch64_pr23870_SOURCES) \
>         flagstest_compress_debug_sections_zstd.c \
>         flagstest_o_specialfile.c \
>         flagstest_o_specialfile_and_compress_debug_sections.c \
> -       flagstest_o_ttext_1.c icf_virtual_function_folding_test.c \
> -       $(ifuncmain1_SOURCES) ifuncmain1pic.c ifuncmain1picstatic.c \
> -       ifuncmain1pie.c $(ifuncmain1static_SOURCES) \
> -       ifuncmain1staticpic.c ifuncmain1staticpie.c \
> -       $(ifuncmain1vis_SOURCES) ifuncmain1vispic.c ifuncmain1vispie.c \
> -       $(ifuncmain2_SOURCES) ifuncmain2pic.c ifuncmain2picstatic.c \
> +       flagstest_o_ttext_1.c $(hidden_weak_undef_SOURCES) \
> +       icf_virtual_function_folding_test.c $(ifuncmain1_SOURCES) \
> +       ifuncmain1pic.c ifuncmain1picstatic.c ifuncmain1pie.c \
> +       $(ifuncmain1static_SOURCES) ifuncmain1staticpic.c \
> +       ifuncmain1staticpie.c $(ifuncmain1vis_SOURCES) \
> +       ifuncmain1vispic.c ifuncmain1vispie.c $(ifuncmain2_SOURCES) \
> +       ifuncmain2pic.c ifuncmain2picstatic.c \
>         $(ifuncmain2static_SOURCES) $(ifuncmain3_SOURCES) \
>         $(ifuncmain4_SOURCES) ifuncmain4picstatic.c \
>         $(ifuncmain4static_SOURCES) $(ifuncmain5_SOURCES) \
> @@ -3480,6 +3487,9 @@ DEPENDENCIES = \
>  @DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@SPLIT_DEFSYMS = --defsym __morestack=0x100 --defsym __morestack_non_split=0x200
>  @DEFAULT_TARGET_X32_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@SPLIT_DEFSYMS = --defsym __morestack=0x100 --defsym __morestack_non_split=0x200
>  @DEFAULT_TARGET_X86_64_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@SPLIT_DEFSYMS = --defsym __morestack=0x100 --defsym __morestack_non_split=0x200
> +hidden_weak_undef_SOURCES = hidden_weak_undef.c
> +hidden_weak_undef_CFLAGS = -fPIE
> +hidden_weak_undef_LDFLAGS = -pie
>  all: $(BUILT_SOURCES)
>         $(MAKE) $(AM_MAKEFLAGS) all-am
>
> @@ -3762,6 +3772,10 @@ exclude_libs_test$(EXEEXT): $(exclude_libs_test_OBJECTS) $(exclude_libs_test_DEP
>  @NATIVE_LINKER_FALSE@  @rm -f flagstest_o_ttext_1$(EXEEXT)
>  @NATIVE_LINKER_FALSE@  $(AM_V_CCLD)$(LINK) $(flagstest_o_ttext_1_OBJECTS) $(flagstest_o_ttext_1_LDADD) $(LIBS)
>
> +hidden_weak_undef$(EXEEXT): $(hidden_weak_undef_OBJECTS) $(hidden_weak_undef_DEPENDENCIES) $(EXTRA_hidden_weak_undef_DEPENDENCIES)
> +       @rm -f hidden_weak_undef$(EXEEXT)
> +       $(AM_V_CCLD)$(hidden_weak_undef_LINK) $(hidden_weak_undef_OBJECTS) $(hidden_weak_undef_LDADD) $(LIBS)
> +
>  @GCC_FALSE@icf_virtual_function_folding_test$(EXEEXT): $(icf_virtual_function_folding_test_OBJECTS) $(icf_virtual_function_folding_test_DEPENDENCIES) $(EXTRA_icf_virtual_function_folding_test_DEPENDENCIES)
>  @GCC_FALSE@    @rm -f icf_virtual_function_folding_test$(EXEEXT)
>  @GCC_FALSE@    $(AM_V_CCLD)$(LINK) $(icf_virtual_function_folding_test_OBJECTS) $(icf_virtual_function_folding_test_LDADD) $(LIBS)
> @@ -4862,6 +4876,7 @@ distclean-compile:
>  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flagstest_o_specialfile.Po@am__quote@
>  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flagstest_o_specialfile_and_compress_debug_sections.Po@am__quote@
>  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flagstest_o_ttext_1.Po@am__quote@
> +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hidden_weak_undef-hidden_weak_undef.Po@am__quote@
>  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icf_virtual_function_folding_test.Po@am__quote@
>  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ifuncdep2.Po@am__quote@
>  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ifuncmain1.Po@am__quote@
> @@ -5007,6 +5022,20 @@ distclean-compile:
>  @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
>  @am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
>
> +hidden_weak_undef-hidden_weak_undef.o: hidden_weak_undef.c
> +@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hidden_weak_undef_CFLAGS) $(CFLAGS) -MT hidden_weak_undef-hidden_weak_undef.o -MD -MP -MF $(DEPDIR)/hidden_weak_undef-hidden_weak_undef.Tpo -c -o hidden_weak_undef-hidden_weak_undef.o `test -f 'hidden_weak_undef.c' || echo '$(srcdir)/'`hidden_weak_undef.c
> +@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/hidden_weak_undef-hidden_weak_undef.Tpo $(DEPDIR)/hidden_weak_undef-hidden_weak_undef.Po
> +@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='hidden_weak_undef.c' object='hidden_weak_undef-hidden_weak_undef.o' libtool=no @AMDEPBACKSLASH@
> +@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
> +@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hidden_weak_undef_CFLAGS) $(CFLAGS) -c -o hidden_weak_undef-hidden_weak_undef.o `test -f 'hidden_weak_undef.c' || echo '$(srcdir)/'`hidden_weak_undef.c
> +
> +hidden_weak_undef-hidden_weak_undef.obj: hidden_weak_undef.c
> +@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hidden_weak_undef_CFLAGS) $(CFLAGS) -MT hidden_weak_undef-hidden_weak_undef.obj -MD -MP -MF $(DEPDIR)/hidden_weak_undef-hidden_weak_undef.Tpo -c -o hidden_weak_undef-hidden_weak_undef.obj `if test -f 'hidden_weak_undef.c'; then $(CYGPATH_W) 'hidden_weak_undef.c'; else $(CYGPATH_W) '$(srcdir)/hidden_weak_undef.c'; fi`
> +@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/hidden_weak_undef-hidden_weak_undef.Tpo $(DEPDIR)/hidden_weak_undef-hidden_weak_undef.Po
> +@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='hidden_weak_undef.c' object='hidden_weak_undef-hidden_weak_undef.obj' libtool=no @AMDEPBACKSLASH@
> +@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
> +@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hidden_weak_undef_CFLAGS) $(CFLAGS) -c -o hidden_weak_undef-hidden_weak_undef.obj `if test -f 'hidden_weak_undef.c'; then $(CYGPATH_W) 'hidden_weak_undef.c'; else $(CYGPATH_W) '$(srcdir)/hidden_weak_undef.c'; fi`
> +
>  large-large.o: large.c
>  @am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(large_CFLAGS) $(CFLAGS) -MT large-large.o -MD -MP -MF $(DEPDIR)/large-large.Tpo -c -o large-large.o `test -f 'large.c' || echo '$(srcdir)/'`large.c
>  @am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/large-large.Tpo $(DEPDIR)/large-large.Po
> @@ -7923,6 +7952,13 @@ package_metadata_test.log: package_metadata_test$(EXEEXT)
>         --log-file $$b.log --trs-file $$b.trs \
>         $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
>         "$$tst" $(AM_TESTS_FD_REDIRECT)
> +hidden_weak_undef.log: hidden_weak_undef$(EXEEXT)
> +       @p='hidden_weak_undef$(EXEEXT)'; \
> +       b='hidden_weak_undef'; \
> +       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
> +       --log-file $$b.log --trs-file $$b.trs \
> +       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
> +       "$$tst" $(AM_TESTS_FD_REDIRECT)
>  .test.log:
>         @p='$<'; \
>         $(am__set_b); \
> diff --git a/gold/testsuite/hidden_weak_undef.c b/gold/testsuite/hidden_weak_undef.c
> new file mode 100644
> index 00000000000..01ff447fe69
> --- /dev/null
> +++ b/gold/testsuite/hidden_weak_undef.c
> @@ -0,0 +1,35 @@
> +/* hidden_weak_undef.c -- test hidden weak undefined symbol in PIE.
> +
> +   Copyright (C) 2024 Free Software Foundation, Inc.
> +
> +   This file is part of gold.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program; if not, write to the Free Software
> +   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
> +   MA 02110-1301, USA.  */
> +
> +// Hidden weak undefined symbol in PIE should be resolved to 0.
> +
> +#include <stdlib.h>
> +
> +extern void undefined (void) __attribute__((visibility("hidden"))) __attribute__((weak));
> +
> +int
> +main (void)
> +{
> +  if (&undefined != NULL)
> +    abort ();
> +
> +  return 0;
> +}
> --
> 2.46.0
>

I will check it by the end of this week if there are no objections.
  
Alan Modra Aug. 21, 2024, 5:58 a.m. UTC | #2
On Sat, Aug 17, 2024 at 07:14:53AM -0700, H.J. Lu wrote:
> Hidden weak undefined symbol in PIE should be resolved to 0.

I don't think this patch is correct.  Why single out hidden visibility
rather than testing for non-default visibility?  Also, what is special
about weak symbols?  ie. if the patch is correct for STB_WEAK
undefined, why not STB_GLOBAL undefined?

Also, despite the comment of "Return true if the final value of this
symbol is known at link time", final_value_is_known appears to
actually be "Return true if the value at runtime of this symbol is
known".  That makes me wonder about changes here affecting targets
other than x86.  How did you test the change?
  
H.J. Lu Aug. 21, 2024, 12:33 p.m. UTC | #3
On Tue, Aug 20, 2024 at 10:58 PM Alan Modra <amodra@gmail.com> wrote:
>
> On Sat, Aug 17, 2024 at 07:14:53AM -0700, H.J. Lu wrote:
> > Hidden weak undefined symbol in PIE should be resolved to 0.
>
> I don't think this patch is correct.  Why single out hidden visibility
> rather than testing for non-default visibility?  Also, what is special

There is no STV_PROTECTED undefined symbol.   Only weak
undefined symbols are allowed in executables.   If it isn't STV_HIDDEN,
the symbol may be resolved to non-zero at run-time.

> about weak symbols?  ie. if the patch is correct for STB_WEAK
> undefined, why not STB_GLOBAL undefined?
>
> Also, despite the comment of "Return true if the final value of this
> symbol is known at link time", final_value_is_known appears to
> actually be "Return true if the value at runtime of this symbol is
> known".  That makes me wonder about changes here affecting targets

Hidden undefined symbol is always resolved to 0 at run-time.

> other than x86.  How did you test the change?
>

I added a run-time test and tested it on x86.
  

Patch

diff --git a/gold/symtab.cc b/gold/symtab.cc
index 5857dd7b098..5d7f4d47775 100644
--- a/gold/symtab.cc
+++ b/gold/symtab.cc
@@ -450,7 +450,15 @@  Symbol::final_value_is_known() const
        || parameters->options().relocatable())
       && !(this->type() == elfcpp::STT_TLS
            && parameters->options().pie()))
-    return false;
+    {
+      // Hidden weak undefined in PIE is always resolved to 0.
+      if (this->visibility() == elfcpp::STV_HIDDEN
+	  && this->is_weak_undefined()
+	  && parameters->options().pie())
+	return true;
+
+      return false;
+    }
 
   // If the symbol is not from an object file, and is not undefined,
   // then it is defined, and known.
diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am
index a40f7624395..65d16ba393d 100644
--- a/gold/testsuite/Makefile.am
+++ b/gold/testsuite/Makefile.am
@@ -4531,3 +4531,8 @@  package_metadata_test.o: package_metadata_main.c
 package_metadata_test$(EXEEXT): package_metadata_test.o gcctestdir/ld
 	$(CXXLINK) package_metadata_test.o -Wl,--package-metadata='{"foo":"bar"}'
 	$(TEST_READELF) --notes $@ | grep -q '{"foo":"bar"}'
+
+check_PROGRAMS += hidden_weak_undef
+hidden_weak_undef_SOURCES = hidden_weak_undef.c
+hidden_weak_undef_CFLAGS = -fPIE
+hidden_weak_undef_LDFLAGS = -pie
diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in
index 78ca73acb17..a676a88f7f2 100644
--- a/gold/testsuite/Makefile.in
+++ b/gold/testsuite/Makefile.in
@@ -110,7 +110,7 @@  check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
 	$(am__EXEEXT_40) $(am__EXEEXT_41) $(am__EXEEXT_42) \
 	$(am__EXEEXT_43) $(am__EXEEXT_44) $(am__EXEEXT_45) \
 	$(am__EXEEXT_46) $(am__EXEEXT_47) $(am__EXEEXT_48) \
-	package_metadata_test$(EXEEXT)
+	package_metadata_test$(EXEEXT) hidden_weak_undef$(EXEEXT)
 @NATIVE_OR_CROSS_LINKER_TRUE@am__append_1 = object_unittest \
 @NATIVE_OR_CROSS_LINKER_TRUE@	binary_unittest leb128_unittest \
 @NATIVE_OR_CROSS_LINKER_TRUE@	overflow_unittest
@@ -1598,6 +1598,12 @@  flagstest_o_specialfile_and_compress_debug_sections_LDADD = $(LDADD)
 flagstest_o_ttext_1_SOURCES = flagstest_o_ttext_1.c
 flagstest_o_ttext_1_OBJECTS = flagstest_o_ttext_1.$(OBJEXT)
 flagstest_o_ttext_1_LDADD = $(LDADD)
+am_hidden_weak_undef_OBJECTS =  \
+	hidden_weak_undef-hidden_weak_undef.$(OBJEXT)
+hidden_weak_undef_OBJECTS = $(am_hidden_weak_undef_OBJECTS)
+hidden_weak_undef_LDADD = $(LDADD)
+hidden_weak_undef_LINK = $(CCLD) $(hidden_weak_undef_CFLAGS) $(CFLAGS) \
+	$(hidden_weak_undef_LDFLAGS) $(LDFLAGS) -o $@
 icf_virtual_function_folding_test_SOURCES =  \
 	icf_virtual_function_folding_test.c
 icf_virtual_function_folding_test_OBJECTS =  \
@@ -2340,12 +2346,13 @@  SOURCES = $(libgoldtest_a_SOURCES) $(aarch64_pr23870_SOURCES) \
 	flagstest_compress_debug_sections_zstd.c \
 	flagstest_o_specialfile.c \
 	flagstest_o_specialfile_and_compress_debug_sections.c \
-	flagstest_o_ttext_1.c icf_virtual_function_folding_test.c \
-	$(ifuncmain1_SOURCES) ifuncmain1pic.c ifuncmain1picstatic.c \
-	ifuncmain1pie.c $(ifuncmain1static_SOURCES) \
-	ifuncmain1staticpic.c ifuncmain1staticpie.c \
-	$(ifuncmain1vis_SOURCES) ifuncmain1vispic.c ifuncmain1vispie.c \
-	$(ifuncmain2_SOURCES) ifuncmain2pic.c ifuncmain2picstatic.c \
+	flagstest_o_ttext_1.c $(hidden_weak_undef_SOURCES) \
+	icf_virtual_function_folding_test.c $(ifuncmain1_SOURCES) \
+	ifuncmain1pic.c ifuncmain1picstatic.c ifuncmain1pie.c \
+	$(ifuncmain1static_SOURCES) ifuncmain1staticpic.c \
+	ifuncmain1staticpie.c $(ifuncmain1vis_SOURCES) \
+	ifuncmain1vispic.c ifuncmain1vispie.c $(ifuncmain2_SOURCES) \
+	ifuncmain2pic.c ifuncmain2picstatic.c \
 	$(ifuncmain2static_SOURCES) $(ifuncmain3_SOURCES) \
 	$(ifuncmain4_SOURCES) ifuncmain4picstatic.c \
 	$(ifuncmain4static_SOURCES) $(ifuncmain5_SOURCES) \
@@ -3480,6 +3487,9 @@  DEPENDENCIES = \
 @DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@SPLIT_DEFSYMS = --defsym __morestack=0x100 --defsym __morestack_non_split=0x200
 @DEFAULT_TARGET_X32_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@SPLIT_DEFSYMS = --defsym __morestack=0x100 --defsym __morestack_non_split=0x200
 @DEFAULT_TARGET_X86_64_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@SPLIT_DEFSYMS = --defsym __morestack=0x100 --defsym __morestack_non_split=0x200
+hidden_weak_undef_SOURCES = hidden_weak_undef.c
+hidden_weak_undef_CFLAGS = -fPIE
+hidden_weak_undef_LDFLAGS = -pie
 all: $(BUILT_SOURCES)
 	$(MAKE) $(AM_MAKEFLAGS) all-am
 
@@ -3762,6 +3772,10 @@  exclude_libs_test$(EXEEXT): $(exclude_libs_test_OBJECTS) $(exclude_libs_test_DEP
 @NATIVE_LINKER_FALSE@	@rm -f flagstest_o_ttext_1$(EXEEXT)
 @NATIVE_LINKER_FALSE@	$(AM_V_CCLD)$(LINK) $(flagstest_o_ttext_1_OBJECTS) $(flagstest_o_ttext_1_LDADD) $(LIBS)
 
+hidden_weak_undef$(EXEEXT): $(hidden_weak_undef_OBJECTS) $(hidden_weak_undef_DEPENDENCIES) $(EXTRA_hidden_weak_undef_DEPENDENCIES) 
+	@rm -f hidden_weak_undef$(EXEEXT)
+	$(AM_V_CCLD)$(hidden_weak_undef_LINK) $(hidden_weak_undef_OBJECTS) $(hidden_weak_undef_LDADD) $(LIBS)
+
 @GCC_FALSE@icf_virtual_function_folding_test$(EXEEXT): $(icf_virtual_function_folding_test_OBJECTS) $(icf_virtual_function_folding_test_DEPENDENCIES) $(EXTRA_icf_virtual_function_folding_test_DEPENDENCIES) 
 @GCC_FALSE@	@rm -f icf_virtual_function_folding_test$(EXEEXT)
 @GCC_FALSE@	$(AM_V_CCLD)$(LINK) $(icf_virtual_function_folding_test_OBJECTS) $(icf_virtual_function_folding_test_LDADD) $(LIBS)
@@ -4862,6 +4876,7 @@  distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flagstest_o_specialfile.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flagstest_o_specialfile_and_compress_debug_sections.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flagstest_o_ttext_1.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hidden_weak_undef-hidden_weak_undef.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icf_virtual_function_folding_test.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ifuncdep2.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ifuncmain1.Po@am__quote@
@@ -5007,6 +5022,20 @@  distclean-compile:
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
 
+hidden_weak_undef-hidden_weak_undef.o: hidden_weak_undef.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hidden_weak_undef_CFLAGS) $(CFLAGS) -MT hidden_weak_undef-hidden_weak_undef.o -MD -MP -MF $(DEPDIR)/hidden_weak_undef-hidden_weak_undef.Tpo -c -o hidden_weak_undef-hidden_weak_undef.o `test -f 'hidden_weak_undef.c' || echo '$(srcdir)/'`hidden_weak_undef.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/hidden_weak_undef-hidden_weak_undef.Tpo $(DEPDIR)/hidden_weak_undef-hidden_weak_undef.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='hidden_weak_undef.c' object='hidden_weak_undef-hidden_weak_undef.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hidden_weak_undef_CFLAGS) $(CFLAGS) -c -o hidden_weak_undef-hidden_weak_undef.o `test -f 'hidden_weak_undef.c' || echo '$(srcdir)/'`hidden_weak_undef.c
+
+hidden_weak_undef-hidden_weak_undef.obj: hidden_weak_undef.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hidden_weak_undef_CFLAGS) $(CFLAGS) -MT hidden_weak_undef-hidden_weak_undef.obj -MD -MP -MF $(DEPDIR)/hidden_weak_undef-hidden_weak_undef.Tpo -c -o hidden_weak_undef-hidden_weak_undef.obj `if test -f 'hidden_weak_undef.c'; then $(CYGPATH_W) 'hidden_weak_undef.c'; else $(CYGPATH_W) '$(srcdir)/hidden_weak_undef.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/hidden_weak_undef-hidden_weak_undef.Tpo $(DEPDIR)/hidden_weak_undef-hidden_weak_undef.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='hidden_weak_undef.c' object='hidden_weak_undef-hidden_weak_undef.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hidden_weak_undef_CFLAGS) $(CFLAGS) -c -o hidden_weak_undef-hidden_weak_undef.obj `if test -f 'hidden_weak_undef.c'; then $(CYGPATH_W) 'hidden_weak_undef.c'; else $(CYGPATH_W) '$(srcdir)/hidden_weak_undef.c'; fi`
+
 large-large.o: large.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(large_CFLAGS) $(CFLAGS) -MT large-large.o -MD -MP -MF $(DEPDIR)/large-large.Tpo -c -o large-large.o `test -f 'large.c' || echo '$(srcdir)/'`large.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/large-large.Tpo $(DEPDIR)/large-large.Po
@@ -7923,6 +7952,13 @@  package_metadata_test.log: package_metadata_test$(EXEEXT)
 	--log-file $$b.log --trs-file $$b.trs \
 	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
 	"$$tst" $(AM_TESTS_FD_REDIRECT)
+hidden_weak_undef.log: hidden_weak_undef$(EXEEXT)
+	@p='hidden_weak_undef$(EXEEXT)'; \
+	b='hidden_weak_undef'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
 .test.log:
 	@p='$<'; \
 	$(am__set_b); \
diff --git a/gold/testsuite/hidden_weak_undef.c b/gold/testsuite/hidden_weak_undef.c
new file mode 100644
index 00000000000..01ff447fe69
--- /dev/null
+++ b/gold/testsuite/hidden_weak_undef.c
@@ -0,0 +1,35 @@ 
+/* hidden_weak_undef.c -- test hidden weak undefined symbol in PIE.
+
+   Copyright (C) 2024 Free Software Foundation, Inc.
+
+   This file is part of gold.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
+// Hidden weak undefined symbol in PIE should be resolved to 0.
+
+#include <stdlib.h>
+
+extern void undefined (void) __attribute__((visibility("hidden"))) __attribute__((weak));
+
+int
+main (void)
+{
+  if (&undefined != NULL)
+    abort ();
+
+  return 0;
+}