diff mbox

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

Message ID 1380881101-8581-1-git-send-email-vgupta@synopsys.com
State New
Headers show

Commit Message

Vineet Gupta Oct. 4, 2013, 10:05 a.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>
Cc: Baruch Siach <baruch@tkos.co.il>
---
 include/netdb.h                          | 2 +-
 libc/misc/internals/__errno_location.c   | 2 +-
 libc/misc/internals/__h_errno_location.c | 2 +-
 libc/sysdeps/linux/common/bits/errno.h   | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

Comments

Baruch Siach Oct. 6, 2013, 3:58 a.m. UTC | #1
Hi Vineet,

On Fri, Oct 04, 2013 at 03:35:01PM +0530, Vineet Gupta wrote:

[snip]

>   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>
> Cc: Baruch Siach <baruch@tkos.co.il>

For xtensa NPTL target:

Tested-by: Baruch Siach <baruch@tkos.co.il>

Thanks,
baruch

> ---
>  include/netdb.h                          | 2 +-
>  libc/misc/internals/__errno_location.c   | 2 +-
>  libc/misc/internals/__h_errno_location.c | 2 +-
>  libc/sysdeps/linux/common/bits/errno.h   | 2 +-
>  4 files changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/include/netdb.h b/include/netdb.h
> index 14cf3d24dae0..8fdfa0fccc7d 100644
> --- a/include/netdb.h
> +++ b/include/netdb.h
> @@ -59,7 +59,7 @@ __BEGIN_DECLS
>  /* Function to get address of global `h_errno' variable.  */
>  extern int *__h_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 *__h_errno_location(void);
>  # endif
>  #endif
> diff --git a/libc/misc/internals/__errno_location.c b/libc/misc/internals/__errno_location.c
> index dec913f3031d..be7a9093efa3 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/misc/internals/__h_errno_location.c b/libc/misc/internals/__h_errno_location.c
> index 41353d74a648..6653681cbf09 100644
> --- a/libc/misc/internals/__h_errno_location.c
> +++ b/libc/misc/internals/__h_errno_location.c
> @@ -16,4 +16,4 @@ int *__h_errno_location(void)
>  {
>      return &h_errno;
>  }
> -libc_hidden_def(__h_errno_location)
> +libc_hidden_weak(__h_errno_location)
> diff --git a/libc/sysdeps/linux/common/bits/errno.h b/libc/sysdeps/linux/common/bits/errno.h
> index 7ef1b9440a34..777338fb1e0a 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 Nov. 1, 2013, 6:53 a.m. UTC | #2
Ping^2 !


On 10/04/2013 03:35 PM, 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)
> 
> 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>
> Cc: Baruch Siach <baruch@tkos.co.il>
> ---
>  include/netdb.h                          | 2 +-
>  libc/misc/internals/__errno_location.c   | 2 +-
>  libc/misc/internals/__h_errno_location.c | 2 +-
>  libc/sysdeps/linux/common/bits/errno.h   | 2 +-
>  4 files changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/include/netdb.h b/include/netdb.h
> index 14cf3d24dae0..8fdfa0fccc7d 100644
> --- a/include/netdb.h
> +++ b/include/netdb.h
> @@ -59,7 +59,7 @@ __BEGIN_DECLS
>  /* Function to get address of global `h_errno' variable.  */
>  extern int *__h_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 *__h_errno_location(void);
>  # endif
>  #endif
> diff --git a/libc/misc/internals/__errno_location.c b/libc/misc/internals/__errno_location.c
> index dec913f3031d..be7a9093efa3 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/misc/internals/__h_errno_location.c b/libc/misc/internals/__h_errno_location.c
> index 41353d74a648..6653681cbf09 100644
> --- a/libc/misc/internals/__h_errno_location.c
> +++ b/libc/misc/internals/__h_errno_location.c
> @@ -16,4 +16,4 @@ int *__h_errno_location(void)
>  {
>      return &h_errno;
>  }
> -libc_hidden_def(__h_errno_location)
> +libc_hidden_weak(__h_errno_location)
> diff --git a/libc/sysdeps/linux/common/bits/errno.h b/libc/sysdeps/linux/common/bits/errno.h
> index 7ef1b9440a34..777338fb1e0a 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
>
diff mbox

Patch

diff --git a/include/netdb.h b/include/netdb.h
index 14cf3d24dae0..8fdfa0fccc7d 100644
--- a/include/netdb.h
+++ b/include/netdb.h
@@ -59,7 +59,7 @@  __BEGIN_DECLS
 /* Function to get address of global `h_errno' variable.  */
 extern int *__h_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 *__h_errno_location(void);
 # endif
 #endif
diff --git a/libc/misc/internals/__errno_location.c b/libc/misc/internals/__errno_location.c
index dec913f3031d..be7a9093efa3 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/misc/internals/__h_errno_location.c b/libc/misc/internals/__h_errno_location.c
index 41353d74a648..6653681cbf09 100644
--- a/libc/misc/internals/__h_errno_location.c
+++ b/libc/misc/internals/__h_errno_location.c
@@ -16,4 +16,4 @@  int *__h_errno_location(void)
 {
     return &h_errno;
 }
-libc_hidden_def(__h_errno_location)
+libc_hidden_weak(__h_errno_location)
diff --git a/libc/sysdeps/linux/common/bits/errno.h b/libc/sysdeps/linux/common/bits/errno.h
index 7ef1b9440a34..777338fb1e0a 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