[git commit] Fix weak/strong attribute of __errno_location and it's __GI alias
Bernhard Reutner-Fischer
rep.dot.nop at gmail.com
Wed Nov 6 21:21:59 UTC 2013
commit: http://git.uclibc.org/uClibc/commit/?id=acfc107a50344b100b9ea492678928acc047c6ae
branch: http://git.uclibc.org/uClibc/commit/?id=refs/heads/master
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 at synopsys.com>
Cc: Baruch Siach <baruch at tkos.co.il>
Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop at gmail.com>
---
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 14cf3d2..8fdfa0f 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 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/misc/internals/__h_errno_location.c b/libc/misc/internals/__h_errno_location.c
index 41353d7..6653681 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 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
More information about the uClibc-cvs
mailing list