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

Pali Rohár pali at kernel.org
Mon Mar 8 11:55:32 CET 2021


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.


More information about the U-Boot mailing list