@@ -189,6 +189,16 @@ config UML_TIME_TRAVEL_SUPPORT
It is safe to say Y, but you probably don't need this.
+config UML_USE_BUILT_IN_STRINGS
+ bool
+ default N
+ prompt "Use kernel memcpy, memmove, etc"
+ help
+ UML can use the kernel built in memcpy, memmove, etc functions
+ or use the glibc equivalents instead.
+ The glibc equivalents are slightly faster and will result in a
+ slightly smaller executable when linking UML dynamically.
+
endmenu
source "arch/um/drivers/Kconfig"
new file mode 100644
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * Copyright (C) 2020 Cambridge Greys Ltd.
+ * Copyright (C) 2020 Red Hat Inc.
+ */
+
+#ifndef __ASM_UM_STRING_H
+#define __ASM_UM_STRING_H
+
+#ifndef CONFIG_UML_USE_BUILT_IN_STRINGS
+
+#include <stddef.h>
+
+#define __HAVE_ARCH_STRCPY
+extern char *strcpy(char *dest, const char *src);
+#define __HAVE_ARCH_STRNCPY
+extern char *strncpy(char *dest, const char *src, size_t n);
+#define __HAVE_ARCH_STRCAT
+extern char *strcat(char *dest, const char *src);
+#define __HAVE_ARCH_STRNCAT
+extern char *strncat(char *dest, const char *src, size_t n);
+#define __HAVE_ARCH_STRCMP
+extern int strcmp(const char *s1, const char *s2);
+#define __HAVE_ARCH_STRNCMP
+extern int strncmp(const char *s1, const char *s2, size_t n);
+#define __HAVE_ARCH_STRCHR
+extern char *strchr(const char *s, int c);
+#define __HAVE_ARCH_STRLEN
+extern size_t strlen(const char *s);
+#define __HAVE_ARCH_MEMCPY
+extern void *memcpy(void *dest, const void *src, size_t n);
+#define __HAVE_ARCH_MEMMOVE
+extern void *memmove(void *dest, const void *src, size_t n);
+#define __HAVE_ARCH_MEMCHR
+extern void *memchr(const void *s, int c, size_t n);
+#define __HAVE_ARCH_STRNLEN
+extern size_t strnlen(const char *s, size_t maxlen);
+#define __HAVE_ARCH_STRSTR
+extern char *strstr(const char *haystack, const char *needle);
+#define __HAVE_ARCH_MEMSET
+extern void *memset(void *s, int c, size_t n);
+#define __HAVE_ARCH_STRNCASECMP
+extern int strncasecmp(const char *s1, const char *s2, size_t n);
+#define __HAVE_ARCH_STRCASECMP
+extern int strcasecmp(const char *s1, const char *s2);
+#define __HAVE_ARCH_STRCHRNUL
+extern char *strchrnul(const char *s, int c);
+#define __HAVE_ARCH_STRRCH
+extern char *strchrnul(const char *s, int c);
+#define __HAVE_ARCH_STRSPN
+extern size_t strspn(const char *s, const char *accept);
+#define __HAVE_ARCH_STRCSPN
+extern size_t strcspn(const char *s, const char *reject);
+#define __HAVE_ARCH_STRPBRK
+extern char *strpbrk(const char *s, const char *accept);
+#define __HAVE_ARCH_STRSEP
+extern char *strsep(char **stringp, const char *delim);
+#define __HAVE_ARCH_MEMCMP
+extern int memcmp(const void *s1, const void *s2, size_t n);
+#define __HAVE_ARCH_BCMP
+extern int bcmp(const void *s1, const void *s2, size_t n);
+
+#else
+
+#include <asm-generic/string.h>
+
+#endif
+
+#endif /* __ASM_UM_STRING_H */
@@ -9,6 +9,7 @@
* add an EXPORT for the glibc one.
*/
+#ifdef CONFIG_UML_USE_BUILT_IN_STRINGS
#undef strlen
#undef strstr
#undef memcpy
@@ -17,6 +18,7 @@
extern size_t strlen(const char *);
extern void *memmove(void *, const void *, size_t);
extern void *memset(void *, int, size_t);
+#endif
extern int printf(const char *, ...);
/* If it's not defined, the export is included in lib/string.c.*/
@@ -24,14 +26,38 @@ extern int printf(const char *, ...);
EXPORT_SYMBOL(strstr);
#endif
-#ifndef __x86_64__
+#if !defined(__x86_64__) && defined(CONFIG_UML_USE_BUILT_IN_STRINGS)
extern void *memcpy(void *, const void *, size_t);
EXPORT_SYMBOL(memcpy);
#endif
+
+#ifndef CONFIG_UML_USE_BUILT_IN_STRINGS
+/* These all come from glibc */
+EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(memmove);
EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(printf);
+EXPORT_SYMBOL(strcpy);
+EXPORT_SYMBOL(strncpy);
+EXPORT_SYMBOL(strcat);
+EXPORT_SYMBOL(strncat);
+EXPORT_SYMBOL(strcmp);
+EXPORT_SYMBOL(strncmp);
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(memchr);
+EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(strncasecmp);
+EXPORT_SYMBOL(strcasecmp);
+EXPORT_SYMBOL(strchrnul);
+EXPORT_SYMBOL(strcspn);
+EXPORT_SYMBOL(strpbrk);
+EXPORT_SYMBOL(strsep);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(bcmp);
+
+#endif
/* Here, instead, I can provide a fake prototype. Yes, someone cares: genksyms.
* However, the modules will use the CRC defined *here*, no matter if it is
@@ -20,14 +20,16 @@ ifeq ($(CONFIG_X86_32),y)
obj-y += checksum_32.o syscalls_32.o
obj-$(CONFIG_ELF_CORE) += elfcore.o
-subarch-y = ../lib/string_32.o ../lib/atomic64_32.o ../lib/atomic64_cx8_32.o
+subarch-y = ../lib/atomic64_32.o ../lib/atomic64_cx8_32.o
subarch-y += ../kernel/sys_ia32.o
+subarch-$(CONFIG_UML_USE_BUILT_IN_STRINGS) += ../lib/string_32.o
else
obj-y += syscalls_64.o vdso/
-subarch-y = ../lib/csum-partial_64.o ../lib/memcpy_64.o ../entry/thunk_64.o
+subarch-y = ../lib/csum-partial_64.o ../entry/thunk_64.o
+subarch-$(CONFIG_UML_USE_BUILT_IN_STRINGS) += ../lib/memcpy_64.o
endif