[LEDE-DEV] undefined reference to `memmove' caused by __builtin_memmove()

Felix Fietkau nbd at nbd.name
Mon Feb 27 22:11:27 PST 2017

On 2017-02-20 15:10, Mehrtens, Hauke wrote:
> When I compile MIPS malta with the LEDE patches on kernel 4.9 I get this error in the kernel build:
>   CC      arch/mips/boot/compressed/decompress.o
>   OBJCOPY arch/mips/boot/compressed/vmlinux.bin
>   XZKERN  arch/mips/boot/compressed/vmlinux.bin.z
>   OBJCOPY arch/mips/boot/compressed/piggy.o
>   LD      vmlinuz
> arch/mips/boot/compressed/decompress.o: In function `lzma2_lzma':
> /tmp2/mehrtens/linux/arch/mips/boot/compressed/../../../../lib/xz/xz_dec_lzma2.c:884: undefined reference to `memmove'
> make[1]: *** [vmlinuz] Error 1
> make: *** [vmlinuz] Error 2 
> This is caused by this option selected in the MIPS Malta target: SYS_SUPPORTS_ZBOOT 
> This is caused by this patch from LEDE:
> https://git.lede-project.org/?p=source.git;a=blob;f=target/linux/generic/patches-4.9/306-mips_mem_functions_performance.patch
> This was initially committed here:
> https://git.lede-project.org/?p=source.git;a=commitdiff;h=07e59c7bc7f375f792ec9734be42fe4fa391a8bb
I've pushed a fix to my staging tree, please test.

> When I remove the "#define memmove ..." from the string.h it works
> for me, I also checked the GCC documentation and it does not list
> __builtin_memmove() as an official interface here:
> https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
There's nothing wrong with __builtin_memmove or the function references
that it generates. The problem lies within decompress_unxz.c:

#ifndef memmove
/* Not static to avoid a conflict with the prototype in the Linux
headers. */
void *memmove(void *dest, const void *src, size_t size)

Since the patch adds a #define to string.h, the the custom memmove
function no longer gets emitted, and gcc generates references to it
through __builtin_memmove

> I would like to remove the optimization for memmove as it uses an unofficial GCC API.
It is used in quite a few places, and I it's safe to rely on it.

> The problem is that I do not fully understand this patch and it is not good documented. 
> Why are the __buildin_ functions only called when the length is *not* a __builtin_constant_p() or smaller than 64 bytes?
The length >= 64 check (to force gcc not to inline larger copies) can
only be guaranteed to run at compile time if the pointer is constant.
If it's not constant, the decision on whether to inline it or not is
left to gcc.

> Doesn't the compiler automatically replaces a call to memcpy() and similar functions with the build in version when he things it is good to do so?
When I first added the patch, there were some issues with that. I don't
know if there are any corner cases with current gcc, but the code should
be safe the way it is.

- Felix

More information about the Lede-dev mailing list