Hi!
The autobuilder system of the Buildroot project (which rebuilds packages
for multiple architectures and toolchains) reported an issue when
building s6-rc 0.0.4.0 for ARM using uclibc-ng statically [1]. The build
ends as follows:
```
/accts/mlweber1/instance-2/output/host/arm-buildroot-linux-uclibcgnueabi/sysroot/usr/lib/libc.a(strnlen.os):
In function `strnlen':
strnlen.c:(.text+0x0): multiple definition of `strnlen'
/accts/mlweber1/instance-2/output/host/arm-buildroot-linux-uclibcgnueabi/sysroot/usr/lib/skalibs/libskarnet.a(strnlen.o):strnlen.c:(.text.strnlen+0x0):
first defined here
```
It means that skalibs v2.6.3.0 has been compiled with its internal variant of
strnlen(), as the configuration script failed to detect the one provided by
uclibc-ng.
When trying to recreate the build issue, using a tweaked version of
skalibs/configure gives us more information:
```
/home/eric/build/test-s6-rc-0.0.4.0-arm/host/bin/arm-linux-gcc -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -Isrc/include -Werror=implicit-function-declaration -Werror=implicit-int -Werror=pointer-sign -Werror=pointer-arith -Wno-unused-value -Wno-parentheses -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -pipe -Wall -std=c99 -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables -Wa,--noexecstack -ffunction-sections -fdata-sections -O2 -fomit-frame-pointer -fno-stack-protector -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Os -static -o trystrnlen.o -c src/sysdeps/trystrnlen.c
src/sysdeps/trystrnlen.c: In function 'main':
src/sysdeps/trystrnlen.c:10:10: error: implicit declaration of function 'strnlen' [-Werror=implicit-function-declaration]
return strnlen("/", 1) ;
^~~~~~~
cc1: some warnings being treated as errors
```
The MAN page for strnlen() from glibc states that _POSIX_C_SOURCE should be
defined and uclibc-ng seems to behave the same. The _POSIX_C_SOURCE is indeed
passed by Buildroot to the cross-compiler when build the program.
But since v2.6.3.0, skalibs/src/sysdeps/trystrnlen.c clears the definition of
_POSIX_C_SOURCE. Allowing it again solves the issue: the uclibc-ng version of
strnlen() is detected, skalibs internal variant is disabled and s6-rc-update
statically links with uclibc-ng like a charm.
I tried to statically link with musl and surprisingly, there is no linking error
even though the skalibs variant of strnlen() is enabled and musl provides it
too!
```
$ grep STRNLEN ~/build/demo-s6/qemu/x86/musl/static/staging/usr/include/skalibs/sysdeps.h
#undef SKALIBS_HASSTRNLEN
$ grep STRNLEN ~/build/demo-s6/qemu/x86/uclibc/static/staging/usr/include/skalibs/sysdeps.h
#undef SKALIBS_HASSTRNLEN
```
One of the differences between uclibc-ng and musl is that uclibc-ng, as glibc,
defines strnlen() using libc_hidden_def(strnlen), which results in the following
when inspecting symbols:
```
$ objdump -t ~/build/demo-s6/qemu/x86/musl/static/staging/lib/libc.a | grep strnlen
00000000 *UND* 00000000 strnlen
[...]
00000000 *UND* 00000000 strnlen
strnlen.o: format de fichier elf32-i386
00000000 l df *ABS* 00000000 strnlen.c
00000000 l d .text.strnlen 00000000 .text.strnlen
00000000 g F .text.strnlen 00000033 strnlen
00000000 *UND* 00000000 strnlen
$ objdump -t ~/build/demo-s6/qemu/x86/uclibc/static/staging/usr/lib/libc.a | grep strnlen
00000000 *UND* 00000000 __GI_strnlen
00000000 *UND* 00000000 __GI_strnlen
strnlen.os: format de fichier elf32-i386
00000000 l df *ABS* 00000000 strnlen.c
00000000 l d .text.__GI_strnlen 00000000 .text.__GI_strnlen
00000000 g F .text.__GI_strnlen 00000034 .hidden __GI_strnlen
00000000 g F .text.__GI_strnlen 00000034 strnlen
00000000 *UND* 00000000 __GI_strnlen
```
Would this difference explains why there is no redefinition linking error with
musl, or am I missing something?
What is the reason for clearing _POSIX_C_SOURCE from trystrnlen.c?
[1]
http://autobuild.buildroot.net/results/59f3b6d5fe3e9b561adbafc08eeb1a23f7100278/
Regards,
--
ELB
Received on Sat Jan 13 2018 - 18:12:13 UTC