[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