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

Vineet Gupta Vineet.Gupta1 at synopsys.com
Sat Oct 5 08:14:22 UTC 2013


On 10/04/2013 10:12 PM, Bernhard Reutner-Fischer wrote:
> On 1 October 2013 14:21:44 Vineet Gupta <Vineet.Gupta1 at 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 at 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 at uclibc.org
>> http://lists.busybox.net/mailman/listinfo/uclibc
> 
> 
> 
> Sent with AquaMail for Android
> http://www.aqua-mail.com



More information about the uClibc mailing list