diff mbox

Fix weak/strong attribute of __errno_location and it's __GI alias

Message ID 1380630104-8230-1-git-send-email-vgupta@synopsys.com
State Superseded, archived
Headers show

Commit Message

Vineet Gupta Oct. 1, 2013, 12:21 p.m. UTC
A simple statically linked hello world program was segfaulting for ARC
in linuxthreads.old configuration (although the root casue applies
cross-arch for NPTL as well as linuxthreads.old as described)

The crash was due to branch to NULL in _stdio_init

  0001026c <_stdio_init>:
     1026c:    push_s     blink
     1026e:    st.a       r13,[sp,-8]
     10272:    bl.d       0  --> supposed call to __errno_location

The call was NOT getting patched to libc internal only alias
__GI___errno_location, because it was weak while it's exported cousin,
__errno_location was strong/normal.

  arc-linux-uclibc-nm libc/misc/internals/__errno_location.os

  00000000 W __GI___errno_location
  00000000 T __errno_location

This is exactly opposite to what is expected.

Quoting Peter S. Mazinger, commit 87936cd013041 "errno and *_init cleanup"

 | The rule adopted:
 | for enabled threads we make in libc the __GI_x() variants strong, x() weak
 | and (should) provide another strong x() in libpthread.
 | If threads are disabled, even the __GI_x() variants are weak.

With the fix, we see the right settings as below

  00000000 T __GI___errno_location
  00000000 W __errno_location

Note that problem won't show up in a static busybox build as it references
errno and that seems to elide the issue.

I can confirm the same/more issues with latest ARM buildroot builds w/o
my fix.

(1). linuxthreads.old (broken just like ARC)

  arm-linux-nm uclibc-snapshot/libc/misc/internals/__errno_location.os

  00000000 W __GI___errno_location
  00000000 T __errno_location

  But presumably the issue there is NOT catestrophic because ARM linker is
  likely smarter and patches a NOP instead of NULL branch.

  00008388 <_stdio_init>:
      8388:	e92d4038 	push	{r3, r4, r5, lr}
      838c:	e320f000 	nop	{0}

(2) NPTL build (exported version is not weak)

  00000000 T __GI___errno_location
  00000000 T __errno_location

  This causes a static link with libpthread and test program
  referencing errno to fail to link.

  #include <errno.h>
  int main(void)
  {
      printf("%d\n", errno);
  }

  arm-linux-gcc -static -pthread -o tst tst.o

  arm-buildroot-linux-uclibcgnueabi/sysroot/usr/lib/libc.a(__errno_location.os):
  In function `__errno_location':  __errno_location.c:(.text+0x0):
                           multiple definition of `__errno_location'
  arm-buildroot-linux-uclibcgnueabi/sysroot/usr/lib/libpthread.a
            (errno_location.os):errno_location.c:(.text+0x0): first defined here

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
---
 libc/misc/internals/__errno_location.c | 2 +-
 libc/sysdeps/linux/common/bits/errno.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

Comments

Baruch Siach Oct. 4, 2013, 8:38 a.m. UTC | #1
Hi Vineet,

On Tue, Oct 01, 2013 at 05:51:44PM +0530, Vineet Gupta wrote:
> A simple statically linked hello world program was segfaulting for ARC
> in linuxthreads.old configuration (although the root casue applies
> cross-arch for NPTL as well as linuxthreads.old as described)

I haven't noticed you patch when posting mine 
(http://lists.busybox.net/pipermail/uclibc/2013-October/047962.html). Care to 
add __h_errno_location to your patch?

Thanks,
baruch

> The crash was due to branch to NULL in _stdio_init
> 
>   0001026c <_stdio_init>:
>      1026c:    push_s     blink
>      1026e:    st.a       r13,[sp,-8]
>      10272:    bl.d       0  --> supposed call to __errno_location
> 
> The call was NOT getting patched to libc internal only alias
> __GI___errno_location, because it was weak while it's exported cousin,
> __errno_location was strong/normal.
> 
>   arc-linux-uclibc-nm libc/misc/internals/__errno_location.os
> 
>   00000000 W __GI___errno_location
>   00000000 T __errno_location
> 
> This is exactly opposite to what is expected.
> 
> Quoting Peter S. Mazinger, commit 87936cd013041 "errno and *_init cleanup"
> 
>  | The rule adopted:
>  | for enabled threads we make in libc the __GI_x() variants strong, x() weak
>  | and (should) provide another strong x() in libpthread.
>  | If threads are disabled, even the __GI_x() variants are weak.
> 
> With the fix, we see the right settings as below
> 
>   00000000 T __GI___errno_location
>   00000000 W __errno_location
> 
> Note that problem won't show up in a static busybox build as it references
> errno and that seems to elide the issue.
> 
> I can confirm the same/more issues with latest ARM buildroot builds w/o
> my fix.
> 
> (1). linuxthreads.old (broken just like ARC)
> 
>   arm-linux-nm uclibc-snapshot/libc/misc/internals/__errno_location.os
> 
>   00000000 W __GI___errno_location
>   00000000 T __errno_location
> 
>   But presumably the issue there is NOT catestrophic because ARM linker is
>   likely smarter and patches a NOP instead of NULL branch.
> 
>   00008388 <_stdio_init>:
>       8388:	e92d4038 	push	{r3, r4, r5, lr}
>       838c:	e320f000 	nop	{0}
> 
> (2) NPTL build (exported version is not weak)
> 
>   00000000 T __GI___errno_location
>   00000000 T __errno_location
> 
>   This causes a static link with libpthread and test program
>   referencing errno to fail to link.
> 
>   #include <errno.h>
>   int main(void)
>   {
>       printf("%d\n", errno);
>   }
> 
>   arm-linux-gcc -static -pthread -o tst tst.o
> 
>   arm-buildroot-linux-uclibcgnueabi/sysroot/usr/lib/libc.a(__errno_location.os):
>   In function `__errno_location':  __errno_location.c:(.text+0x0):
>                            multiple definition of `__errno_location'
>   arm-buildroot-linux-uclibcgnueabi/sysroot/usr/lib/libpthread.a
>             (errno_location.os):errno_location.c:(.text+0x0): first defined here
> 
> Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
> ---
>  libc/misc/internals/__errno_location.c | 2 +-
>  libc/sysdeps/linux/common/bits/errno.h | 2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/libc/misc/internals/__errno_location.c b/libc/misc/internals/__errno_location.c
> index dec913f..be7a909 100644
> --- a/libc/misc/internals/__errno_location.c
> +++ b/libc/misc/internals/__errno_location.c
> @@ -16,4 +16,4 @@ int *__errno_location(void)
>  {
>      return &errno;
>  }
> -libc_hidden_def(__errno_location)
> +libc_hidden_weak(__errno_location)
> diff --git a/libc/sysdeps/linux/common/bits/errno.h b/libc/sysdeps/linux/common/bits/errno.h
> index 7ef1b94..777338f 100644
> --- a/libc/sysdeps/linux/common/bits/errno.h
> +++ b/libc/sysdeps/linux/common/bits/errno.h
> @@ -43,7 +43,7 @@
>  /* Function to get address of global `errno' variable.  */
>  extern int *__errno_location (void) __THROW __attribute__ ((__const__));
>  #  ifdef _LIBC
> -#   ifndef __UCLIBC_HAS_TLS__
> +#   if !defined(__UCLIBC_HAS_TLS__) && !defined(__UCLIBC_HAS_THREADS__)
>  extern int weak_const_function *__errno_location(void);
>  #   endif
>  #  endif
> -- 
> 1.8.1.2
Vineet Gupta Oct. 4, 2013, 9:02 a.m. UTC | #2
On 10/04/2013 02:08 PM, Baruch Siach wrote:
> Hi Vineet,
>
> On Tue, Oct 01, 2013 at 05:51:44PM +0530, Vineet Gupta wrote:
>> > A simple statically linked hello world program was segfaulting for ARC
>> > in linuxthreads.old configuration (although the root casue applies
>> > cross-arch for NPTL as well as linuxthreads.old as described)
> I haven't noticed you patch when posting mine 
> (http://lists.busybox.net/pipermail/uclibc/2013-October/047962.html). Care to 
> add __h_errno_location to your patch?
>
> Thanks,
> baruch

Sure thing. I'm rebuilding a toolchain with updated patch now.
FWIW, your patch doesn't contain the hunk for header ifdef'ery which would also be
needed.

-Vineet
Bernhard Reutner-Fischer Oct. 4, 2013, 4:42 p.m. UTC | #3
On 1 October 2013 14:21:44 Vineet Gupta <Vineet.Gupta1@synopsys.com> wrote:
> A simple statically linked hello world program was segfaulting for ARC
> in linuxthreads.old configuration (although the root casue applies
> cross-arch for NPTL as well as linuxthreads.old as described)
>
> The crash was due to branch to NULL in _stdio_init

is this gcc.gnu.org/PR32219 ?
See GCC ML for proposed patches..
Thanks,
>
>   0001026c <_stdio_init>:
>      1026c:    push_s     blink
>      1026e:    st.a       r13,[sp,-8]
>      10272:    bl.d       0  --> supposed call to __errno_location
>
> The call was NOT getting patched to libc internal only alias
> __GI___errno_location, because it was weak while it's exported cousin,
> __errno_location was strong/normal.
>
>   arc-linux-uclibc-nm libc/misc/internals/__errno_location.os
>
>   00000000 W __GI___errno_location
>   00000000 T __errno_location
>
> This is exactly opposite to what is expected.
>
> Quoting Peter S. Mazinger, commit 87936cd013041 "errno and *_init cleanup"
>
>  | The rule adopted:
>  | for enabled threads we make in libc the __GI_x() variants strong, x() weak
>  | and (should) provide another strong x() in libpthread.
>  | If threads are disabled, even the __GI_x() variants are weak.
>
> With the fix, we see the right settings as below
>
>   00000000 T __GI___errno_location
>   00000000 W __errno_location
>
> Note that problem won't show up in a static busybox build as it references
> errno and that seems to elide the issue.
>
> I can confirm the same/more issues with latest ARM buildroot builds w/o
> my fix.
>
> (1). linuxthreads.old (broken just like ARC)
>
>   arm-linux-nm uclibc-snapshot/libc/misc/internals/__errno_location.os
>
>   00000000 W __GI___errno_location
>   00000000 T __errno_location
>
>   But presumably the issue there is NOT catestrophic because ARM linker is
>   likely smarter and patches a NOP instead of NULL branch.
>
>   00008388 <_stdio_init>:
>       8388:	e92d4038 	push	{r3, r4, r5, lr}
>       838c:	e320f000 	nop	{0}
>
> (2) NPTL build (exported version is not weak)
>
>   00000000 T __GI___errno_location
>   00000000 T __errno_location
>
>   This causes a static link with libpthread and test program
>   referencing errno to fail to link.
>
>   #include <errno.h>
>   int main(void)
>   {
>       printf("%d\n", errno);
>   }
>
>   arm-linux-gcc -static -pthread -o tst tst.o
>
>   arm-buildroot-linux-uclibcgnueabi/sysroot/usr/lib/libc.a(__errno_location.os):
>   In function `__errno_location':  __errno_location.c:(.text+0x0):
>                            multiple definition of `__errno_location'
>   arm-buildroot-linux-uclibcgnueabi/sysroot/usr/lib/libpthread.a
>             (errno_location.os):errno_location.c:(.text+0x0): first defined here
>
> Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
> ---
>  libc/misc/internals/__errno_location.c | 2 +-
>  libc/sysdeps/linux/common/bits/errno.h | 2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/libc/misc/internals/__errno_location.c 
> b/libc/misc/internals/__errno_location.c
> index dec913f..be7a909 100644
> --- a/libc/misc/internals/__errno_location.c
> +++ b/libc/misc/internals/__errno_location.c
> @@ -16,4 +16,4 @@ int *__errno_location(void)
>  {
>      return &errno;
>  }
> -libc_hidden_def(__errno_location)
> +libc_hidden_weak(__errno_location)
> diff --git a/libc/sysdeps/linux/common/bits/errno.h 
> b/libc/sysdeps/linux/common/bits/errno.h
> index 7ef1b94..777338f 100644
> --- a/libc/sysdeps/linux/common/bits/errno.h
> +++ b/libc/sysdeps/linux/common/bits/errno.h
> @@ -43,7 +43,7 @@
>  /* Function to get address of global `errno' variable.  */
>  extern int *__errno_location (void) __THROW __attribute__ ((__const__));
>  #  ifdef _LIBC
> -#   ifndef __UCLIBC_HAS_TLS__
> +#   if !defined(__UCLIBC_HAS_TLS__) && !defined(__UCLIBC_HAS_THREADS__)
>  extern int weak_const_function *__errno_location(void);
>  #   endif
>  #  endif
> --
> 1.8.1.2
>
> _______________________________________________
> uClibc mailing list
> uClibc@uclibc.org
> http://lists.busybox.net/mailman/listinfo/uclibc



Sent with AquaMail for Android
http://www.aqua-mail.com
Vineet Gupta Oct. 5, 2013, 8:14 a.m. UTC | #4
On 10/04/2013 10:12 PM, Bernhard Reutner-Fischer wrote:
> On 1 October 2013 14:21:44 Vineet Gupta <Vineet.Gupta1@synopsys.com> wrote:
>> A simple statically linked hello world program was segfaulting for ARC
>> in linuxthreads.old configuration (although the root casue applies
>> cross-arch for NPTL as well as linuxthreads.old as described)
>>
>> The crash was due to branch to NULL in _stdio_init
> 
> is this gcc.gnu.org/PR32219 ?
> See GCC ML for proposed patches..
> Thanks,

Nope, I don't think this specific case is related to that PR.
There are actually 2 issues here:

1. For NPTL config, uClibc is not attributing vanilla __errno_location to be weak.
This causes the redefinition when static linking with libpthread which defines
it's own strong __errno_location. This is a regression due to commit
f418f52701de02 "errno, h_errno: correct them for non-TLS". So one of the hunks in
my patch fixes that.

2. With above, for !NPTL case, now both __errno_location and it's GI alias become
weak. That should only happen when we don't have any threading library as !NPTL is
true when we have linuxthreads.old.

This understanding comes from an existing commig log.

Quoting Peter S. Mazinger, commit 87936cd013041 "errno and *_init cleanup"

  | The rule adopted:
  | for enabled threads we make in libc the __GI_x() variants strong, x() weak
  | and (should) provide another strong x() in libpthread.
  | If threads are disabled, even the __GI_x() variants are weak.


P.S. My Patch v2, attributed to comments from Baruch is better, since it handles
__h_errno as well. Baruch, whenever you get a chance, can you please give it a
quick spin so we can have a Tested-by or some such from you.

>>
>>   0001026c <_stdio_init>:
>>      1026c:    push_s     blink
>>      1026e:    st.a       r13,[sp,-8]
>>      10272:    bl.d       0  --> supposed call to __errno_location
>>
>> The call was NOT getting patched to libc internal only alias
>> __GI___errno_location, because it was weak while it's exported cousin,
>> __errno_location was strong/normal.
>>
>>   arc-linux-uclibc-nm libc/misc/internals/__errno_location.os
>>
>>   00000000 W __GI___errno_location
>>   00000000 T __errno_location
>>
>> This is exactly opposite to what is expected.
>>
>> Quoting Peter S. Mazinger, commit 87936cd013041 "errno and *_init cleanup"
>>
>>  | The rule adopted:
>>  | for enabled threads we make in libc the __GI_x() variants strong, x() weak
>>  | and (should) provide another strong x() in libpthread.
>>  | If threads are disabled, even the __GI_x() variants are weak.
>>
>> With the fix, we see the right settings as below
>>
>>   00000000 T __GI___errno_location
>>   00000000 W __errno_location
>>
>> Note that problem won't show up in a static busybox build as it references
>> errno and that seems to elide the issue.
>>
>> I can confirm the same/more issues with latest ARM buildroot builds w/o
>> my fix.
>>
>> (1). linuxthreads.old (broken just like ARC)
>>
>>   arm-linux-nm uclibc-snapshot/libc/misc/internals/__errno_location.os
>>
>>   00000000 W __GI___errno_location
>>   00000000 T __errno_location
>>
>>   But presumably the issue there is NOT catestrophic because ARM linker is
>>   likely smarter and patches a NOP instead of NULL branch.
>>
>>   00008388 <_stdio_init>:
>>       8388:    e92d4038     push    {r3, r4, r5, lr}
>>       838c:    e320f000     nop    {0}
>>
>> (2) NPTL build (exported version is not weak)
>>
>>   00000000 T __GI___errno_location
>>   00000000 T __errno_location
>>
>>   This causes a static link with libpthread and test program
>>   referencing errno to fail to link.
>>
>>   #include <errno.h>
>>   int main(void)
>>   {
>>       printf("%d\n", errno);
>>   }
>>
>>   arm-linux-gcc -static -pthread -o tst tst.o
>>
>>   arm-buildroot-linux-uclibcgnueabi/sysroot/usr/lib/libc.a(__errno_location.os):
>>   In function `__errno_location':  __errno_location.c:(.text+0x0):
>>                            multiple definition of `__errno_location'
>>   arm-buildroot-linux-uclibcgnueabi/sysroot/usr/lib/libpthread.a
>>             (errno_location.os):errno_location.c:(.text+0x0): first defined here
>>
>> Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
>> ---
>>  libc/misc/internals/__errno_location.c | 2 +-
>>  libc/sysdeps/linux/common/bits/errno.h | 2 +-
>>  2 files changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/libc/misc/internals/__errno_location.c
>> b/libc/misc/internals/__errno_location.c
>> index dec913f..be7a909 100644
>> --- a/libc/misc/internals/__errno_location.c
>> +++ b/libc/misc/internals/__errno_location.c
>> @@ -16,4 +16,4 @@ int *__errno_location(void)
>>  {
>>      return &errno;
>>  }
>> -libc_hidden_def(__errno_location)
>> +libc_hidden_weak(__errno_location)
>> diff --git a/libc/sysdeps/linux/common/bits/errno.h
>> b/libc/sysdeps/linux/common/bits/errno.h
>> index 7ef1b94..777338f 100644
>> --- a/libc/sysdeps/linux/common/bits/errno.h
>> +++ b/libc/sysdeps/linux/common/bits/errno.h
>> @@ -43,7 +43,7 @@
>>  /* Function to get address of global `errno' variable.  */
>>  extern int *__errno_location (void) __THROW __attribute__ ((__const__));
>>  #  ifdef _LIBC
>> -#   ifndef __UCLIBC_HAS_TLS__
>> +#   if !defined(__UCLIBC_HAS_TLS__) && !defined(__UCLIBC_HAS_THREADS__)
>>  extern int weak_const_function *__errno_location(void);
>>  #   endif
>>  #  endif
>> -- 
>> 1.8.1.2
>>
>> _______________________________________________
>> uClibc mailing list
>> uClibc@uclibc.org
>> http://lists.busybox.net/mailman/listinfo/uclibc
> 
> 
> 
> Sent with AquaMail for Android
> http://www.aqua-mail.com
Vineet Gupta Oct. 11, 2013, 1:39 p.m. UTC | #5
On 10/04/2013 10:12 PM, Bernhard Reutner-Fischer wrote:
> On 1 October 2013 14:21:44 Vineet Gupta <Vineet.Gupta1@synopsys.com> wrote:
>> A simple statically linked hello world program was segfaulting for ARC
>> in linuxthreads.old configuration (although the root casue applies
>> cross-arch for NPTL as well as linuxthreads.old as described)
>>
>> The crash was due to branch to NULL in _stdio_init
> 
> is this gcc.gnu.org/PR32219 ?
> See GCC ML for proposed patches..
> Thanks,

Thinking about this a bit - you are probably right that this is due to GCC PR -
i.e. __GI_errno_location being weak/hidden.

However the fix to make it strong, is not a workaround for that PR - but because
it needs to be strong anyways.

And alternately, the exportable version __errno_location needs to be weak so that
we don't get redefs when static linking with libpthread etc.

Is this convincing enough to get this v2 patch into trunk :-)

Thx,
-Vineet
Bernhard Reutner-Fischer Oct. 12, 2013, 9:59 a.m. UTC | #6
On 11 October 2013 15:39:00 Vineet Gupta <Vineet.Gupta1@synopsys.com> wrote:
> On 10/04/2013 10:12 PM, Bernhard Reutner-Fischer wrote:
> > On 1 October 2013 14:21:44 Vineet Gupta <Vineet.Gupta1@synopsys.com> wrote:
> >> A simple statically linked hello world program was segfaulting for ARC
> >> in linuxthreads.old configuration (although the root casue applies
> >> cross-arch for NPTL as well as linuxthreads.old as described)
> >>
> >> The crash was due to branch to NULL in _stdio_init
> > is this gcc.gnu.org/PR32219 ?
> > See GCC ML for proposed patches..
> > Thanks,
>
> Thinking about this a bit - you are probably right that this is due to GCC PR -
> i.e. __GI_errno_location being weak/hidden.
>
> However the fix to make it strong, is not a workaround for that PR - but 
> because
> it needs to be strong anyways.
>
> And alternately, the exportable version __errno_location needs to be weak 
> so that
> we don't get redefs when static linking with libpthread etc.
>
> Is this convincing enough to get this v2 patch into trunk :-)

I will push this, thanks.
>
> Thx,
> -Vineet
>
>



Sent with AquaMail for Android
http://www.aqua-mail.com
Vineet Gupta Oct. 18, 2013, 11:26 a.m. UTC | #7
Ping ?

Gentle Reminder !

-Vineet

On 10/12/2013 03:29 PM, Bernhard Reutner-Fischer wrote:
> On 11 October 2013 15:39:00 Vineet Gupta <Vineet.Gupta1@synopsys.com> wrote:
>> On 10/04/2013 10:12 PM, Bernhard Reutner-Fischer wrote:
>> > On 1 October 2013 14:21:44 Vineet Gupta <Vineet.Gupta1@synopsys.com> wrote:
>> >> A simple statically linked hello world program was segfaulting for ARC
>> >> in linuxthreads.old configuration (although the root casue applies
>> >> cross-arch for NPTL as well as linuxthreads.old as described)
>> >>
>> >> The crash was due to branch to NULL in _stdio_init
>> > is this gcc.gnu.org/PR32219 ?
>> > See GCC ML for proposed patches..
>> > Thanks,
>>
>> Thinking about this a bit - you are probably right that this is due to GCC PR -
>> i.e. __GI_errno_location being weak/hidden.
>>
>> However the fix to make it strong, is not a workaround for that PR - but because
>> it needs to be strong anyways.
>>
>> And alternately, the exportable version __errno_location needs to be weak so that
>> we don't get redefs when static linking with libpthread etc.
>>
>> Is this convincing enough to get this v2 patch into trunk :-)
> 
> I will push this, thanks.
>>
>> Thx,
>> -Vineet
>>
>>
> 
> 
> 
> Sent with AquaMail for Android
> http://www.aqua-mail.com
diff mbox

Patch

diff --git a/libc/misc/internals/__errno_location.c b/libc/misc/internals/__errno_location.c
index dec913f..be7a909 100644
--- a/libc/misc/internals/__errno_location.c
+++ b/libc/misc/internals/__errno_location.c
@@ -16,4 +16,4 @@  int *__errno_location(void)
 {
     return &errno;
 }
-libc_hidden_def(__errno_location)
+libc_hidden_weak(__errno_location)
diff --git a/libc/sysdeps/linux/common/bits/errno.h b/libc/sysdeps/linux/common/bits/errno.h
index 7ef1b94..777338f 100644
--- a/libc/sysdeps/linux/common/bits/errno.h
+++ b/libc/sysdeps/linux/common/bits/errno.h
@@ -43,7 +43,7 @@ 
 /* Function to get address of global `errno' variable.  */
 extern int *__errno_location (void) __THROW __attribute__ ((__const__));
 #  ifdef _LIBC
-#   ifndef __UCLIBC_HAS_TLS__
+#   if !defined(__UCLIBC_HAS_TLS__) && !defined(__UCLIBC_HAS_THREADS__)
 extern int weak_const_function *__errno_location(void);
 #   endif
 #  endif