[yocto] Problems building U-Boot for x86_64

Ferry Toth ftoth at telfort.nl
Thu Aug 24 14:34:56 PDT 2017


Op Thu, 24 Aug 2017 16:35:05 +0000, schreef Ferry Toth:

> Op Thu, 24 Aug 2017 17:48:55 +0200, schreef Stefano Babic:
> 
>> Hi Ferry,
>> 
>> On 24/08/2017 15:09, Ferry Toth wrote:
>>> Op Thu, 24 Aug 2017 12:40:57 +0200, schreef Stefano Babic:
>>> 
>>>> Hi Ferry,
>>>>
>>>> On 24/08/2017 08:51, Ferry Toth wrote:
>>>>> Op Wed, 23 Aug 2017 21:07:56 -0700, schreef Khem Raj:
>>>>>
>>>>>> On 8/23/17 3:40 PM, Ferry Toth wrote:
>>>>>>> Op Wed, 23 Aug 2017 14:51:55 -0700, schreef Khem Raj:
>>>>>>>
>>>>>>>> On 8/23/17 2:29 PM, Ferry Toth wrote:
>>>>>>>>> Ferry Toth wrote:
>>>>>>>>>
>>>>>>>>>> Khem Raj wrote:
>>>>>>>>>>
>>>>>>>>>>> On 8/22/17 11:41 PM, Ferry Toth wrote:
>>>>>>>>>>>> I am having trouble building a specific U-Boot version with
>>>>>>>>>>>> Yocto.
>>>>>>>>>>>> Outside of Yocto on 64 bit Ubuntu 17.04 with multilib it
>>>>>>>>>>>> builds fine.
>>>>>>>>>>>>
>>>>>>>>>>>> I am extending meta-intel-edison to build a 64 bit Poke
>>>>>>>>>>>> Morty,
>>>>>>>>>>>> with a vanilla 64-bit kernel (4.12). This is working quite
>>>>>>>>>>>> well.
>>>>>>>>>>>>
>>>>>>>>>>>> My host is x86_64, the target is core2 with tune=core-64.
>>>>>>>>>>>>
>>>>>>>>>>>> Without 64bit tune I can build U-Boot fine. With 64bit it can
>>>>>>>>>>>> not link, appearently because it needs lbgcc.a
>>>>>>>>>>>
>>>>>>>>>>> what is exact error message ? is it while compiling host bits
>>>>>>>>>>> or target bits ?
>>>>>>>>>>
>>>>>>>>>> The failing line is:
>>>>>>>>>> x86_64-poky-linux-ld.bfd -Bsymbolic -Bsymbolic-functions -m
>>>>>>>>>> elf_i386 --emit- relocs --wrap=__divdi3 --wrap=__udivdi3
>>>>>>>>>> --wrap=__moddi3 --wrap=__umoddi3 -- gc-sections -pie -Bstatic
>>>>>>>>>> --no-dynamic-linker -Ttext 0x01101000 -o u-boot -T u-boot.lds
>>>>>>>>>> arch/x86/cpu/start.o --start-group arch/x86/cpu/built-in.o
>>>>>>>>>> arch/x86/lib/built-in.o board/intel/edison/built-in.o
>>>>>>>>>> cmd/built-in.o common/built-in.o disk/built-in.o
>>>>>>>>>> drivers/built-in.o drivers/dma/built-in.o
>>>>>>>>>> drivers/gpio/built-in.o drivers/i2c/built-in.o
>>>>>>>>>> drivers/mmc/built-in.o drivers/mtd/built-in.o
>>>>>>>>>> drivers/mtd/onenand/built-in.o drivers/mtd/spi/built- in.o
>>>>>>>>>> drivers/net/built-in.o drivers/net/phy/built-in.o
>>>>>>>>>> drivers/pci/built-
>>>>>>>>>> in.o drivers/power/built-in.o drivers/power/battery/built-in.o
>>>>>>>>>> drivers/power/domain/built-in.o
>>>>>>>>>> drivers/power/fuel_gauge/built-in.o
>>>>>>>>>> drivers/power/mfd/built-in.o drivers/power/pmic/built-in.o
>>>>>>>>>> drivers/power/regulator/built-in.o drivers/serial/built-in.o
>>>>>>>>>> drivers/spi/built-in.o drivers/usb/common/built-in.o
>>>>>>>>>> drivers/usb/dwc3/built- in.o drivers/usb/emul/built-in.o
>>>>>>>>>> drivers/usb/eth/built-in.o drivers/usb/gadget/built-in.o
>>>>>>>>>> drivers/usb/gadget/udc/built-in.o drivers/usb/host/built-in.o
>>>>>>>>>> drivers/usb/musb-new/built-in.o drivers/usb/musb/built-in.o
>>>>>>>>>> drivers/usb/phy/built-in.o drivers/usb/ulpi/built-in.o
>>>>>>>>>> dts/built-in.o fs/built-in.o lib/built-in.o net/built-in.o
>>>>>>>>>> test/built-in.o test/dm/built-in.o --end-group
>>>>>>>>>> arch/x86/lib/lib.a -Map u-boot.map ERROR: oe_runmake failed
>>>>>>>>>> arch/x86/lib/built-in.o: In function `__wrap___udivdi3':
>>>>>>>>>> /home/ferry/tmp/edison-intel/my/edison-
>>>>>>>>>> morty/out/linux64/build/tmp/work/edison-poky-linux/u-boot/
> edison-
>>>>>>> v2017.03-
>>>>>>>>>> r0/git/arch/x86/lib/gcc.c:25: undefined reference to
>>>>>>>>>> `__normal___udivdi3'
>>>>>>>>>
>>>>>>>>> I as believe the missing lib is libgcc.a I just my sysroot and
>>>>>>>>> found it here:
>>>>>>>>
>>>>>>>> the linker cmdline above does not link with libgcc and there
>>>>>>>> might be a good reason for that, many standalone applications
>>>>>>>> dont link with libgcc intentionally. You could look into the code
>>>>>>>> and see if it can be written differently such that gcc does not
>>>>>>>> have to invoke a helper function from gcc runtime. Another option
>>>>>>>> is to link with libgcc explicitly
>>>>>>>
>>>>>>> If change my setup to build for a 32bit target, it build u-boot
>>>>>>> without error.
>>>>>>
>>>>>> compiler may not be generating calls for the missing function.
>>>>>
>>>>> That would be a bug then? Regardless if I set tune=core-64 or not
>>>>> the resulting U-Boot should be the same.
>>>>>
>>>>>>> When I build the same git outside yocto on 64bit with multilib
>>>>>>> installed it also builds without error. In that case the make
>>>>>>> command would be: make -j8 edison_defconfig
>>>>>>
>>>>>> same is possible. Can you do readelf -sW gcc.o and see if there is
>>>>>> a undefined reference to __normal___udivdi3
>>>>>>
>>>>> I will do that tonight.
>>>>>
>>>>>>> My conclusion: I have some bb variable set to the wrong value or I
>>>>>>> need to get multilib installed into
>>>>>>> /..../sysroots/x86_64-linux/lib.
>>>>>>>
>>>>>>> So how to do that?
>>>>>>>
>>>>>>>>> sysroots/lib32-edison/usr/lib/i686-pokymllib32-linux/6.2.0/
>>>>>>>>> sysroots/lib32-edison-tcbootstrap/usr/lib/i686-pokymllib32-
>>>>> linux/6.2.0/
>>>>>>>>> sysroots/edison/usr/lib64/x86_64-poky-linux/6.2.0/
>>>>>>>>> sysroots/edison-tcbootstrap/usr/lib64/x86_64-poky-linux/6.2.0/
>>>>>>>>>
>>>>>>>>> How compile log shows:
>>>>>>>>> NOTE: make -j8 CROSS_COMPILE=x86_64-poky-linux-
>>>>>>>>> CC=x86_64-poky-linux-gcc --sysroot=/..../sysroots/edison V=1
>>>>>>>>> HOSTCC=gcc -isystem/..../sysroots/x86_64-linux/usr/include -O2
>>>>>>>>> -pipe -L/..../sysroots/x86_64-linux/usr/lib
>>>>>>>>> -L/..../sysroots/x86_64-linux/lib
>>>>>>>>> -Wl,-rpath-link,/..../sysroots/x86_64-linux/usr/lib
>>>>>>>>> -Wl,-rpath-link,/..../sysroots/x86_64-linux/lib
>>>>>>>>> -Wl,-rpath,/..../sysroots/x86_64-linux/usr/lib
>>>>>>>>> -Wl,-rpath,/..../sysroots/x86_64-linux/lib -Wl,-O1 -C
>>>>>>>>> /..../out/linux64/build/tmp/work/edison-poky-linux/u-boot/
edison-
>>>>>>>>> v2017.03-r0/git
>>>>>>>>> O=/..../out/linux64/build/tmp/work/edison-poky-linux/u-
>>>>>>>>> boot/edison-v2017.03-r0/build edison_defconfig
>>>>>>>>>
>>>>>>>>> (.... my edits to shorten the uninteresting part of the path)
>>>>>>>>>
>>>>>>>>> I would think: --sysroot points to /edison dir which actually
>>>>>>>>> contains libgcc.a, but -i, _l and -W1 options point to host dirs
>>>>>>>>> that don't have the lib.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>>>> I attempted to add multilib, but although that immediately
>>>>>>>>>>>> exposed bugs in other recipes but actually adds libgcc.a, it
>>>>>>>>>>>> does that for the target sysroot only.
>>>>>>>>>>>>
>>>>>>>>>>>> And for some reason, U-Boot is built with the native gcc
>>>>>>>>>>>> (x86_64-linux),
>>>>>>>>>>>> and multilib does not add libgcc.a to that sysroot.
>>>>>>>>>>>>
>>>>>>>>>>>> So, how do I add multilib to -native sysroot, preferably only
>>>>>>>>>>>> to -native and not to the target, as the target has not
>>>>>>>>>>>> further use for it?
>>>>>>>>>>>>
>>>>>>>>>>>> Strangest thing is in u-boot.inc there is:
>>>>>>>>>>>> EXTRA_OEMAKE = 'CROSS_COMPILE=${TARGET_PREFIX}
>>>>>>>>>>>> CC="${TARGET_PREFIX}gcc ${TOOLCHAIN_OPTIONS}" V=1'
>>>>>>>>>>>> EXTRA_OEMAKE += 'HOSTCC="${BUILD_CC} ${BUILD_CFLAGS}
>>>>>>>>>>>> ${BUILD_LDFLAGS}"'
>>>>>>>>>>>>
>>>>>>>>>>>> But when I check my log file:
>>>>>>>>>>>> NOTE: make -j8 CROSS_COMPILE=x86_64-poky-linux-
>>>>>>>>>>>> CC=x86_64-poky-linux- gcc  ......
>>>>>>>>>>>>
>>>>>>>>>>>> So TARGET_PREFIX resolves to x86_64-poky-linux, but I think
>>>>>>>>>>>> my target is core2_64 (or something like that). Is that
>>>>>>>>>>>> normal for U-Boot?
>>>>>>>>>>>
>>>>>>>>>>> thats ok.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>> I am a little lost, so any help would be greatly appreciated!
>>>>>>>>>>>>
>>>>>>>>>>>> Ferry
>>>>
>>>> This is a known problem in U-Boot for x86 and it is not yet *cleaned*
>>>> solved. U-Boot for x86 is a 32 bit - there are just disadvantages to
>>>> go to 64 bit version because it is overkilling for a bootloader . The
>>>> issue
>>> 
>>> Alright then. But I didn't intend to build a 64 bit U-Boot. I intended
>>> to build a 64 bit image, which consists in the end of 3 binary image,
>>> U- Boot, Linux and rootfs. The bitness of U-Boot should not depend on
>>> either host or target bitness, it should only depend on the
>>> architectures requirements.
>> 
>> Right, but you cannot build a 64-bit U-Boot: it is unsupported. In
>> fact,
>> when U-Boot is built, gcc is called with -march=i386 -m32.
> 
> That is exactly as it should be.
> 
>> If you check any compiled file, you get a 32 bit object, even if you
>> set tune=core-64.
> 
> Exactly, but I will double check, just to see if there is something
> wrong with the recipe.
> 
> 
>>>> is, as you have found, the libgcc.a library, because the library
>>>> supplied with the host distro is used. This is solved in an elegant
>>>> way with other architectures (PowerPC, ARM) because the required
>>>> (just a few) functions taken from libgcc.a are reimplemented in
>>>> U-Boot (see CONFIG_USE_PRIVATE_LIBGCC, too.) . But this was not done
>>>> for X86, because host and target shared (until 64 bit came) the same
>>>> architecture and the host library is taken. However, this breaks in
>>>> Yocto because the generated library (and then, 64 bit) is taken.
>>> 
>>> Still don't get this. When I build outside of Yocto on a 64 bit host,
>>> it just builds. U-Boot's make file already selects the correct target
>>> bitness and finds the correct libraries.
>> 
>> Right, if you have multilib support. Then you have 32-bit version of
>> libgcc.a
>> 
>>> To me that sounds like that building inside Yocto should just work
>>> too,
>>> if I just get the configuration right.
>> 
>> You built for 64 bit - when the arch/x86/Makefile in U-Boot is called,
>> it tries to find the library itself:
>> 
>> $(shell $(CC) $(PLATFORM_CPPFLAGS) -print-libgcc-file-name)
>> 
>> This always results in the 64bit version of the library built by Yocto.
>> So you have all U-Boot objects built with "-m32" (32 bit objects) and
>> it tries to link against 64 bit libgcc.
> 
> But that would also happens on the host platform (building outside
> Yocto)
> and it doesn't. The host does have multilib and in some genious way gcc
> finds the 32 bit lib and links against it.
> 
>> At least, this what I deducted from the errors...
>> 
>> 
>>> And correct me if I'm wrong, to do that that I need to force Yocto to
>>> build 32 bit target, in case of U-Boot (lib32-u-boot?).
>> 
>> This is already done in U-Boot Makefiles. The architecture is
>> overwritten because "m32" is set inside U-Boot Makefile (just for x86).
>> 
>>> Or override tune=core-64 for U-Boot only?
>>> 
>>> Still, when I build on my host outside of Yocto I don't need to do any
>>> of this. And the linker probably uses 32 bit copy of libgcc.a
>>> installed with multilib on my host.
>> 
>> Absolutely right.
> 
> But the host platform is 64 bit, so that probably shows in
> $(PLATFORM_CPPFLAGS). Everything is built 32 bit due to U-Boot's m32
> override. So how does it know where to find the 32 bit lib?
>> 
>>> Hence my question: Yocto has multilib, which in this case installs 32
>>> bit libs into the targets sysroot. And I suspect I need to install 32
>>> bit libs into the -native sysroot. How to do that? All the
>>> documentation I found are related to installing libs into the target
>>> image.
>> 
>> I don't know - I have given up this way because it looks to me messy to
>> have multilib just for getting libgcc.a to link u-boot.
> 
> The patch below is to find a 32 bit version of the library, put it
> somewhere and patch U-Boot to use that. That sounds way more messy than
> installing installing multilib into the -native envirnment.
> 
> Except I am not sure if that can be done.
> 
> I could try to build U-Boot in the sdk or target environment, as that
> has multilib, but probably the U-Boot image will then be misplaced.
> 
> I could also tell bitbake to use the host compiler and environment, but
> that then puts requirement on the hosts gcc alternatives and puts a
> requirement for multilib on the host actually being installed.

I think I get it. The problem is not that I am building for a 64 bit 
target as this is overruled by U-Boot make. The problem is that it needs 
the 32 bit lib in the -native sysroot. And if the following feature 
request https://bugzilla.yoctoproject.org/show_bug.cgi?id=7960 is current 
it is not (yet) possible to add the lib using multilib.

However, on a 32-bit host the -native sysroot would be i686 and the 
target will be crosscompiled to x86-64, except for U-Boot which will 
still overrule that and build 32-bit, with the 32-bit lib now present.

So, on a x86-64 host I need to overrule bitbake detecting the host arch 
and using that for the -native arch and instead build a i686 -native 
sysroot - which should still run on a 64-bit host.

Otherwise, building U-Boot outside Yocto is the most practical solution. 

> 
>>>> The right and cleanest solution should be to fix in U-Boot just as it
>>>> was done with other architectures.
> 
> Yes, as I understand now, it is not even possible to build U-Boot for
> x86 on an arm platform. Strange.
> 
>>> I think I saw something upstreamed related to this, I'd prefer to wait
>>> till that lands.
>> 
>> I have not yet seen it, it looks I missed that fix.

I probably got that mixed up with another issue.

>>> But I will try to let Yocto apply a patch, instead of adding to my
>>> git.
>>> 
>>>> The workaround I used in a couple of projects is to store in my
>>>> custom meta layer a 32 bit copy of libgcc.a and patch U-Boot to use
>>>> this instead of the library in the distro, that is in :
>>>>
>>>>
>>>> diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index
>>>> e17f0bb..62764ec 100644 --- a/arch/x86/lib/Makefile +++
>>>> b/arch/x86/lib/Makefile @@ -40,7 +40,9 @@ obj-$(CONFIG_HAVE_FSP) +=
>>>> fsp/
>>>>
>>>>  extra-$(CONFIG_USE_PRIVATE_LIBGCC) += lib.a
>>>>
>>>> -NORMAL_LIBGCC = $(shell $(CC) $(PLATFORM_CPPFLAGS)
>>>> -print-libgcc-file-name) +#NORMAL_LIBGCC = $(shell $(CC)
>>>> $(PLATFORM_CPPFLAGS)
>>>> -print-libgcc-file-name)
>>>> +NORMAL_LIBGCC = $(PWD)/arch/$(ARCH)/lib/libgcc.a
>>>>  OBJCOPYFLAGS := --prefix-symbols=__normal_ $(obj)/lib.a:
>>>>  $(NORMAL_LIBGCC) FORCE
>>>> +       echo "Library GCC" ${NORMAL_LIBGCC}
>>>>         $(call if_changed,objcopy)
>>>> --
>>>>
>>>> I hope this helps.
>>>>
>>>>
>>>>
>> Best regards,
>> Stefano --
>> =====================================================================
>> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
>> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
>> Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email:
>> sbabic at denx.de
>> =====================================================================





More information about the yocto mailing list