[CRIU] [PATCH 04/23] pie: provide own memcpy for x86
Kir Kolyshkin
kir at openvz.org
Tue Oct 11 18:46:42 PDT 2016
When compiling criu with clang, I discovered compilation fails like
this:
GEN criu/pie/restorer-blob.h
restorer_blob: Error (compel/src/lib/handle-elf-host.c:328): Unexpected
undefined symbol: `memcpy'. External symbol in PIE?
This happens because clang emits a call to memcpy for struct
initialization (specifically, struct vdso_symtable in vdso_proxify()).
Naturally, as pie is complied without libc there is no memcpy()
so "compel piegen" rightfully complains.
There are a number of possible solutions to that:
1. Write our own vdso_init_symtable() function instead of using =
2. Use some compiler flags that disables using memcpy
3. Provide own version of memcpy
Now, (1) looks ugly, (2) I was not able to find such flags. Another
argument in favor of (3) is we already have implementation of
builtin_memcpy() optimized for x86.
The only problem is it is not named memcpy(). Using assembler file (.S)
we can have a function with two names (entry points).
For a similar issue in ppc, see commits 0570dd8 and 1ad7817. Ultimately,
we should get rid of builtin_mem* names and just use memcpy(), memcmp()
etc, which in case of non-libc linked objects are to be provided by us.
Cc: Laurent Dufour <ldufour at linux.vnet.ibm.com>
Cc: Cyrill Gorcunov <gorcunov at openvz.org>
Signed-off-by: Kir Kolyshkin <kir at openvz.org>
---
criu/arch/x86/include/asm/string.h | 19 ++++++++-----------
criu/arch/x86/memcpy.S | 30 ++++++++++++++++++++++++++++++
criu/pie/Makefile.library | 1 +
3 files changed, 39 insertions(+), 11 deletions(-)
create mode 100644 criu/arch/x86/memcpy.S
diff --git a/criu/arch/x86/include/asm/string.h b/criu/arch/x86/include/asm/string.h
index e1d875e..ca4d4ab 100644
--- a/criu/arch/x86/include/asm/string.h
+++ b/criu/arch/x86/include/asm/string.h
@@ -6,19 +6,16 @@
#include "compiler.h"
#include "asm-generic/string.h"
-static always_inline void *builtin_memcpy(void *to, const void *from, unsigned int n)
+#ifdef CR_NOGLIBC
+extern void *memcpy_x86(void *to, const void *from, size_t n);
+static inline void *builtin_memcpy(void *to, const void *from, size_t n)
{
- int d0, d1, d2;
- asm volatile("rep ; movsl \n"
- "movl %4,%%ecx \n"
- "andl $3,%%ecx \n"
- "jz 1f \n"
- "rep ; movsb \n"
- "1:"
- : "=&c" (d0), "=&D" (d1), "=&S" (d2)
- : "0" (n / 4), "g" (n), "1" ((long)to), "2" ((long)from)
- : "memory");
+ if (n)
+ memcpy_x86(to, from, n);
return to;
}
+#else
+#define builtin_memcpy memcpy
+#endif /* CR_NOGLIBC */
#endif /* __CR_ASM_STRING_H__ */
diff --git a/criu/arch/x86/memcpy.S b/criu/arch/x86/memcpy.S
new file mode 100644
index 0000000..3d6cb19
--- /dev/null
+++ b/criu/arch/x86/memcpy.S
@@ -0,0 +1,30 @@
+#include "asm/linkage.h"
+
+/* The following code is taken from Linux kernel (arch/x86/lib/memcpy_64.S).
+ * There are 3 implementations in there, we use the one that relies on
+ * X86_FEATURE_REP_GOOD ("rep microcode works well").
+ */
+
+/*
+ * memcpy - Copy a memory block.
+ *
+ * Input:
+ * rdi destination
+ * rsi source
+ * rdx count
+ *
+ * Output:
+ * rax original destination
+ */
+ENTRY(memcpy_x86)
+ENTRY(memcpy)
+ movq %rdi, %rax
+ movq %rdx, %rcx
+ shrq $3, %rcx
+ andl $7, %edx
+ rep movsq
+ movl %edx, %ecx
+ rep movsb
+ ret
+END(memcpy)
+END(memcpy_x86)
diff --git a/criu/pie/Makefile.library b/criu/pie/Makefile.library
index e1e28c0..c00877f 100644
--- a/criu/pie/Makefile.library
+++ b/criu/pie/Makefile.library
@@ -13,6 +13,7 @@ ifeq ($(ARCH),x86)
CFLAGS_native += -DCONFIG_X86_64
CFLAGS_compat += -fno-pic -m32 -DCONFIG_X86_32
CFLAGS_util-vdso-elf32.o += -DCONFIG_X86_32
+ OBJS += ./$(ARCH_DIR)/memcpy.o
endif
OBJS += log-simple.o util-fd.o util.o
--
2.7.4
More information about the CRIU
mailing list