[PATCH 2/2] arch/{sparc,sparc64}/Makefile: define ARCH_FPIC

Denys Vlasenko vda.linux at googlemail.com
Wed Jul 19 16:13:18 UTC 2017


On Wed, Jul 19, 2017 at 6:01 PM, Denys Vlasenko
<vda.linux at googlemail.com> wrote:
> On Tue, Jul 18, 2017 at 11:40 PM, Thomas Petazzoni
> <thomas.petazzoni at free-electrons.com> wrote:
>> Hello,
>>
>> On Sat, 15 Jul 2017 14:44:21 +0200, Denys Vlasenko wrote:
>>
>>> Can you investigate this further?
>>> LIBBUSYBOX build results in entire busybox code being put into a library.
>>>
>>> nm -D libbusybox.so.1.28.0.git
>>>
>>> shows that there are only defined entry points to each applet's main():
>>>
>>> 0007b159 T bunzip2_main
>>> 0007c8db T bzip2_main
>>> 000677bb T cal_main
>>> 0008e08e T cat_main
>>>
>>> (so, at max less than 350 entry points), and references to libc functions:
>>>
>>>          U asprintf
>>>          U atof
>>>          U atoi
>>>
>>> No internal libbb functions or variables are exposed.
>>>
>>> I don't understand the error messages you are seeing. bb_errno should
>>> have hidden visibility,
>>> meaning that it is an internal (to libbusybox.so) label, and all
>>> references to it
>>> should be resolved without any shared linker magic. .LCn labels are
>>> similar, they are
>>> referring to text strings (messages and such).
>>>
>>> What is going on? Why your linker has relocations between individual
>>> .o files which go
>>> to the same library?
>>
>> I'm not really sure what's going on. But the problem can very easily be
>> reproduced:
>>
>> $ git clone git://git.buildroot.org/buildroot
>> $ cd buildroot/
>> $ cat > .config <<EOF
>> BR2_sparc=y
>> BR2_TOOLCHAIN_EXTERNAL=y
>> BR2_TOOLCHAIN_EXTERNAL_DOWNLOAD=y
>> BR2_TOOLCHAIN_EXTERNAL_URL="http://autobuild.buildroot.org/toolchains/tarballs/br-sparc-uclibc-2017.05-1078-g95b1dae.tar.bz2"
>> BR2_TOOLCHAIN_EXTERNAL_GCC_6=y
>> BR2_TOOLCHAIN_EXTERNAL_HEADERS_4_1=y
>> BR2_TOOLCHAIN_EXTERNAL_LOCALE=y
>> # BR2_TOOLCHAIN_EXTERNAL_HAS_THREADS_DEBUG is not set
>> BR2_TOOLCHAIN_EXTERNAL_CXX=y
>> BR2_INIT_NONE=y
>> BR2_SYSTEM_BIN_SH_NONE=y
>> BR2_PACKAGE_BUSYBOX_INDIVIDUAL_BINARIES=y
>> # BR2_TARGET_ROOTFS_TAR is not set
>> EOF
>> $ make olddefconfig
>> $ make
>>
>> It builds only Busybox, so it's very quick to reach the build failure.
>> This time, I got:
>>
>> libbb/lib.a(appletlib.o): In function `find_applet_by_name':
>> appletlib.c:(.text.find_applet_by_name+0x14): relocation truncated to fit: R_SPARC_GOT13 against symbol `applet_nameofs' defined in .rodata.applet_nameofs section in libbb/lib.a(appletlib.o)
>> appletlib.c:(.text.find_applet_by_name+0x18): relocation truncated to fit: R_SPARC_GOT13 against symbol `applet_names' defined in .rodata.applet_names section in libbb/lib.a(appletlib.o)
>> libbb/lib.a(appletlib.o): In function `bb_show_usage':
>> appletlib.c:(.text.bb_show_usage+0x10): relocation truncated to fit: R_SPARC_GOT13 against symbol `applet_name' defined in COMMON section in libbb/lib.a(appletlib.o)
>> appletlib.c:(.text.bb_show_usage+0x54): relocation truncated to fit: R_SPARC_GOT13 against symbol `bb_banner' defined in .rodata.bb_banner section in libbb/lib.a(messages.o)
>> libbb/lib.a(appletlib.o): In function `lbb_prepare':
>> appletlib.c:(.text.lbb_prepare+0x18): relocation truncated to fit: R_SPARC_GOT13 against symbol `bb_errno' defined in COMMON section in libbb/lib.a(ptr_to_globals.o)
>> appletlib.c:(.text.lbb_prepare+0x20): relocation truncated to fit: R_SPARC_GOT13 against symbol `applet_name' defined in COMMON section in libbb/lib.a(appletlib.o)
>> libbb/lib.a(appletlib.o): In function `run_applet_no_and_exit':
>> appletlib.c:(.text.run_applet_no_and_exit+0x28): relocation truncated to fit: R_SPARC_GOT13 against symbol `xfunc_error_retval' defined in .data.xfunc_error_retval section in libbb/lib.a(default_error_retval.o)
>> appletlib.c:(.text.run_applet_no_and_exit+0x38): relocation truncated to fit: R_SPARC_GOT13 against symbol `applet_name' defined in COMMON section in libbb/lib.a(appletlib.o)
>> appletlib.c:(.text.run_applet_no_and_exit+0xb0): relocation truncated to fit: R_SPARC_GOT13 against symbol `applet_main' defined in .data.rel.ro.applet_main section in libbb/lib.a(appletlib.o)
>> appletlib.c:(.text.run_applet_no_and_exit+0xcc): relocation truncated to fit: R_SPARC_GOT13 against symbol `applet_suid' defined in .rodata.applet_suid section in libbb/lib.a(appletlib.o)
>> appletlib.c:(.text.run_applet_no_and_exit+0x11c): additional relocation overflows omitted from the output
>> collect2: error: ld returned 1 exit status
>>
>> When I build with my patches (the build is successful), and then look
>> at libbbusybox.so with readelf, the .got section is indeed very small,
>> much smaller than the 8 KB limit detailed in gcc's documentation about
>> -fpic vs. -fPIC:
>>
>> $ ./output/host/usr/bin/sparc-linux-readelf -a output/target/lib/libbusybox.so.1.26.2 | grep "\.got"
>>   [17] .got              PROGBITS        000dc000 0cc000 00021c 04  WA  0   0  4
>>
>> So the size is only 0x21c.
>>
>> Any idea on how to investigate this further?
>
> I think what happens is compiler does not know where applet_names[] are,
> assumes it's in another library and generates a reloc.
> Then, the "short" fpic reloc does not work at link time.

With -fPIC:

00013cc4 <find_applet_by_name>:
   13cc4:    9d e3 bf a0     save  %sp, -96, %sp
   13cc8:    2f 00 03 50     sethi  %hi(0xd4000), %l7
   13ccc:    40 00 02 2d     call  14580 <__sparc_get_pc_thunk.l7>
   13cd0:    ae 05 e3 34     add  %l7, 0x334, %l7    ! d4334 <cpdext+0xd>
   13cd4:    39 00 00 92     sethi  %hi(0x24800), %i4   <== applet_nameofs
   13cd8:    b8 1f 3e 28     xor  %i4, -472, %i4        <== applet_nameofs
   13cdc:    b6 10 27 b8     mov  0x7b8, %i3
   13ce0:    b8 05 c0 1c     add  %l7, %i4, %i4
   13ce4:    03 00 00 5a     sethi  %hi(0x16800), %g1   <== applet_names
   13ce8:    82 18 7c bb     xor  %g1, -837, %g1        <== applet_names
   13cec:    fa 17 20 0c     lduh  [ %i4 + 0xc ], %i5
   13cf0:    b4 05 c0 01     add  %l7, %g1, %i2
   13cf4:    90 10 00 18     mov  %i0, %o0
   13cf8:    ba 07 40 1a     add  %i5, %i2, %i5
   13cfc:    40 03 54 17     call  e8d58 <strcmp at plt>

Static build:

00013c54 <find_applet_by_name>:
   13c54:    9d e3 bf a0     save  %sp, -96, %sp
   13c58:    37 00 02 dc     sethi  %hi(0xb7000), %i3  applet_nameofs
   13c5c:    35 00 03 14     sethi  %hi(0xc5000), %i2  applet_names
   13c60:    b6 16 e3 6c     or  %i3, 0x36c, %i3       applet_nameofs
   13c64:    b8 10 27 b8     mov  0x7b8, %i4
   13c68:    b4 16 a1 ff     or  %i2, 0x1ff, %i2       applet_names
   13c6c:    fa 16 e0 0c     lduh  [ %i3 + 0xc ], %i5
   13c70:    90 10 00 18     mov  %i0, %o0
   13c74:    ba 07 40 1a     add  %i5, %i2, %i5
   13c78:    40 03 1b be     call  dab70 <strcmp at plt>

I think what happens is, with static build, linker uses different relocs,
because it knows it will be allowed to edit text segment when binary gets build.

For library, it uses relocs which allow library's text to stay unchanged
when it is linked against other libraries.

What linker does not know is that applet_names[] is in _this_ library.
Need to find a way to tell it that.


More information about the busybox mailing list