[Buildroot] [PATCH] autossh: honour LDFLAGS
Max Filippov
jcmvbkbc at gmail.com
Fri Dec 2 05:12:34 UTC 2016
Hello,
TL;DR: -static is good, order of objects in libc.a is important.
On Tue, Nov 29, 2016 at 9:00 PM, Waldemar Brodkorb <wbx at openadk.org> wrote:
>> On Tue, Nov 29, 2016 at 12:43 AM, Thomas Petazzoni
>> <thomas.petazzoni at free-electrons.com> wrote:
>> > On Tue, 29 Nov 2016 05:16:55 +0100, Waldemar Brodkorb wrote:
>> >> > The --start-group/--end-group ask the linker to loop between -lgcc and
>> >> > -lc until all unresolved symbols have been resolved. So
>> >> > dl_iterate_phdr() being defined in the C library, but used in libgcc, I
>> >> > guess the dynamic way (-lgcc -lc -lgcc) doesn't work.
>> >>
>> >> But why gcc behaves different?
>> >> BR+gcc5+uClibc-ng-1.0.17 - no extra -static in LDFLAGS required
>> >> BR+gcc5+musl+static - no extra -static in LDFLAGS required
>> >> BR+gcc5+uClibc-ng-1.0.19 - extra -static required!
>> >
>> > I would suspect it's a fallout of the "merge everything in libc"
>> > change, but I really can't figure out why that would make a difference.
>> >
>> > Could it be that with older uClibc versions, gcc was not finding the
>> > dl_iterate_phdr symbol in uClibc, and therefore disabling the unwind
>> > code, and now, due to a change in uClibc, gcc sees the dl_iterate_phdr
>> > symbol, enables unwinding support, which cause this extra reference
>> > from libgcc to libc?
>>
>> No. The difference is in the __pthread_initialize_minimal function.
>> Prior to uclibc-1.0.18 release it used to work because a call to
>> __pthread_initialize_minimal from __uClibc_init was resolved to
>> a function defined in libpthread/nptl/sysdeps/generic/libc-tls.c
>> which didn't reference pthread_unwind.
>> Now it is resolved to a function from
>> libpthread/linuxthreads/pthread.c, and that file pulls in other
>> unused functions, which reference __GI___pthread_unwind,
>> and all the way down to the dl_iterate_phdr.
>>
>> More details:
>> http://lists.busybox.net/pipermail/buildroot/2016-November/177477.html
>
> Sorry that I didn't looked into your report in more detail last time.
> May be I was too confused ;)
>
> I really can't imagine that any code from libpthread/linuxthreads
> can be involved when we compile Xtensa with NPTL support.
Oops, wrong path, wrong searching tool. But the idea:
in the failing case __pthread_initialize_minimal is taken from
libpthread/nptl/init.c and it's way bigger than
__pthread_initialize_minimal used for linking with the uClibc-ng-1.0.17.
Now, I believe that adding the missing -static is the right
solution, because even with uClibc-ng-1.0.17 the linking fails
for a simple application that uses pthread:
$ cat hello.c
#include <pthread.h>
int main()
{
pthread_create(NULL, NULL, NULL, NULL);
return 0;
}
$ xtensa-buildroot-linux-uclibc-gcc -pthread hello.c -o hello
.../libgcc.a(unwind-dw2-fde-dip.o): In function `__gthread_mutex_lock':
.../gthr-default.h:748: undefined reference to `dl_iterate_phdr'
collect2: error: ld returned 1 exit status
The only thing that worries me at this point is that now we have
a lot of pthread internals linked into the program image even when
the program doesn't use them.
E.g. autossh built with uClibc-ng-1.0.17:
$ size -A autossh
autossh:
section size addr
.text 63771 4194484
.rodata 28112 4258256
.eh_frame 792 4286368
.tbss 8 4291256
.ctors 8 4291256
.dtors 8 4291264
.jcr 4 4291272
.data.rel.ro 160 4291276
.data 692 4291440
.bss 15524 4292136
.comment 31 0
.xtensa.info 56 0
.debug_aranges 288 0
.debug_info 2195 0
.debug_abbrev 398 0
.debug_line 6327 0
.debug_frame 40 0
.debug_str 468 0
.debug_loc 40 0
.xt.lit 3752 0
.xt.prop 58596 0
Total 181270
$ nm autossh | grep pthread | wc -l
10
vs. autossh built with uClibc-ng-1.0.19:
$ size -A autossh
autossh:
section size addr
.text 83955 4194484
.rodata 28564 4278440
.eh_frame 1628 4307004
.tdata 4 4312728
.tbss 8 4312732
.ctors 8 4312732
.dtors 8 4312740
.jcr 4 4312748
.data.rel.ro 160 4312752
.data 736 4312912
.bss 24516 4313648
.comment 35 0
.xtensa.info 56 0
.debug_aranges 384 0
.debug_info 20096 0
.debug_abbrev 2925 0
.debug_line 14492 0
.debug_frame 1432 0
.debug_str 4789 0
.debug_loc 11212 0
.debug_ranges 608 0
.xt.lit 4384 0
.xt.prop 77364 0
Total 277368
$ nm autossh | grep pthread | wc -l
77
That makes me wonder, how pthread initialization is done
in uClibc-ng-1.0.17 for applications that use pthread and that
don't. So what I see is the following:
- an application that uses pthread_create references
libpthread/nptl/init.c (because pthread_create.c includes
allocatestack.c, which references __xidcmd defined in init.c
from its __nptl_setxid) and thus gets __pthread_initialize_minimal
from it.
- an application that doesn't use pthread_create gets its weakly
defined __pthread_initialize_minimal from the
libpthread/nptl/sysdeps/generic/libc-tls.c, which provides
__libc_setup_tls referenced from the __uClibc_init.
So we're interested in the following three files:
- init.os (built from libpthread/nptl/init.c, with strong
__pthread_initialize_minimal)
- libc-tls.os (built from libpthread/nptl/sysdeps/xtensa/libc-tls.c,
with weak __pthread_initialize_minimal)
- __uClibc_main.os (built from libc/misc/internal/__uClibc_main.c
with undefined reference to __pthread_initialize_minimal).
Comparing uClibc-ng-1.0.17 with uClibc-ng-1.0.19 I see the following:
1.0.17 had libc.a with libc-tls.os and __uClibc_main.os and
libpthread.a with init.os.
1.0.19 has libc.a with libc-tls.os, __uClibc_main.os and init.os in it
in that order.
I haven't found any related documentation, but apparently with 1.0.19
when a definition of __pthread_initialize_minimal is searched for the
undefined symbol in __uClibc_main.os, the init.os is considered
first. Manually removing and re-adding libc-tls.os and init.os so
that the final order is __uClibc_main.os, libc-tls.os and init.os
restores the 1.0.17 behavior.
> Prior to 1.0.18 libpthread.so was linked with special LDFLAGS:
> LDFLAGS-libpthread.so +=
> $(top_builddir)lib/$(UCLIBC_LDSO_NAME)-$(VERSION).so
> $(top_builddir)lib/libdl-$(VERSION).so \
> -Wl,-z,nodelete,-z,initfirst,-init=$(SYMBOL_PREFIX)__pthread_initialize_minimal_internal
>
> May be this might be a reason we see different behavior.
AFAICS it only affects shared library, i.e. not related to static linking case.
--
Thanks.
-- Max
More information about the buildroot
mailing list