[PATCH u-boot 12/39] string: make memcpy() and memset() visible to fix LTO linking errors

Marek Behun marek.behun at nic.cz
Mon Mar 8 12:36:32 CET 2021


On Mon, 8 Mar 2021 11:55:32 +0100
Pali Rohár <pali at kernel.org> wrote:

> On Monday 08 March 2021 18:40:58 Bin Meng wrote:
> > On Mon, Mar 8, 2021 at 6:23 PM Pali Rohár <pali at kernel.org> wrote:  
> > >
> > > On Monday 08 March 2021 11:19:33 Marek Behun wrote:  
> > > > On Mon, 8 Mar 2021 15:56:01 +0800
> > > > Bin Meng <bmeng.cn at gmail.com> wrote:
> > > >  
> > > > > Hi Marek,
> > > > >
> > > > > On Sun, Mar 7, 2021 at 12:26 PM Marek Behún <marek.behun at nic.cz> wrote:  
> > > > > >
> > > > > > It seems that sometimes (happening on ARM64, for example with
> > > > > > turris_mox_defconfig) GCC, when linking with LTO, changes the symbol
> > > > > > names of some functions, for example lib/string.c's memcpy() function to
> > > > > > memcpy.isra.0.
> > > > > >
> > > > > > This is a problem however when GCC for a code such as this:
> > > > > >         struct some_struct *info = get_some_struct();
> > > > > >         struct some struct tmpinfo;
> > > > > >         tmpinfo = *info;
> > > > > > emits a call to memcpy() by builtin behaviour, to copy *info to tmpinfo.
> > > > > > memset() can be generated sometimes as well.
> > > > > >
> > > > > > This then results in the following linking error:
> > > > > >   .../lz4.c:93: undefined reference to `memcpy'
> > > > > >   .../uuid.c:206: more undefined references to `memcpy' follow
> > > > > >
> > > > > > Make memcpy() and memset() visible by using the __used macro to avoid
> > > > > > this error.  
> > > > >
> > > > > This sounds like a GCC bug of using -fno-builtin and -flto. Could you
> > > > > file a bugzilla to GCC people to get some comments?  
> > > >
> > > > This is not LTO related. -fno-builtin still generates memcpy() call for
> > > > the following code:
> > > >
> > > > typedef struct {
> > > >       int a[40];
> > > >       char b[50];
> > > >       int c[60];
> > > > } a;
> > > >
> > > > void cp(a *d, const a *s) {
> > > >       *d = *s;
> > > > }
> > > >
> > > > when compiled with
> > > >   armv7a-hardfloat-linux-gnueabi-gcc -O2 -fno-builtin -ffreestanding \
> > > >    -nostdlib -S
> > > >
> > > > it produces code
> > > >
> > > >       push    {r4, lr}
> > > >       mov     ip, #4096
> > > >       sub     ip, sp, ip
> > > >       str     r0, [ip, #4088]
> > > >       mov     r2, #452
> > > >       bl      memcpy
> > > >       pop     {r4, pc}
> > > >       .size   cp, .-cp
> > > >
> > > > I don't think this is a bug. Or if it is, it is a wontfix. Just
> > > > implement memcpy into your code, so that gcc does not have to emit
> > > > shitstorms of instructions because of assignment operator :)
> > > >
> > > > Marek  
> > >
> > > This is not a bug but rather a feature of gcc. Documentation for
> > > -nodefaultlibs and -nostdlib contains:
> > >
> > > The compiler may generate calls to "memcmp", "memset", "memcpy" and
> > > "memmove".  These entries are usually resolved by entries in libc.
> > > These entry points should be supplied through some other mechanism when
> > > this option is specified.  
> > 
> > Yeah I know this. My question was why when LTO is enabled, we have to
> > explicitly mark these APIs as __used? I should have asked clearly, is
> > this a bug of LTO?  
> 
> I see... What is the _exact_ command line arguments called when this
> linking issue happen? I know that when gcc's LTO is enabled it depends
> on other of objects and libraries which are linking. And I'm not sure if
> all -whole-archive option can make order of archives independent when
> dealing with these builtin function references. At least I cannot find
> exact gcc documentation about linking order.

Soo, it seems that the compiler generates a copy of memcpy called
memcpy.isra.0 which is a version with -fipa-sra optimization.

Then it thinks the original memcpy is not used, since it replaces all
calls to memcpy.isra.0, but the original memcpy is still being called
for assignment operator. So maybe it is a bug of gcc, and gcc should
use memcpy.isra.0 for the assignment operator as well...


More information about the U-Boot mailing list