Commit 0367a1f6 authored by Kir Kolyshkin's avatar Kir Kolyshkin Committed by Pavel Emelyanov

Drop prefix from own memcpy/memset/memcmp

C compiler might generate calls to memcpy, memset, memcmp, and memmove
as it seem fit (so far we haven't seen memmove being required). That
means we need to provide our own versions of it for code which is not
linked to a libc.

We already have a solution for that in commit bdf60512
("pie: provide memcpy/memcmp/memset for noglibc case")
but we faced another problem of compiler trying to optimize
our builtin_memset() by inserting calls to memset() which
is just an alias in our case and so it lead to infinite recursion.
This was workarounded in commit 8ea0ba7d ("string.h: fix memset
over-optimization with clang") but it's not clear that was a proper
fix.

This patch is considered to be the real solution. As we don't have
any other implementations of memset/memcpy/memcmp in non-libc case,
we can call ours without any prefixes and avoid using weak aliases.

Implementation notes:

1. mem*() functions code had to be moved from .h to .c for the functions
to be compatible with their prototypes declared in /usr/include/string.h
(i.e. "extern").

2. FORTIFY_SOURCE needed to be disabled for code not linked to libc,
because otherwise memcpy() may be replaced with a macro that expands
to __memcpy_chk() which of course can't be resolved during linking.

https://travis-ci.org/kolyshkin/criu/builds/198415449Signed-off-by: 's avatarKir Kolyshkin <kir@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
parent 5abbb791
#ifndef __CR_ASM_STRING_H__
#define __CR_ASM_STRING_H__
#include "common/compiler.h"
#include "asm-generic/string.h"
#endif /* __CR_ASM_STRING_H__ */
#ifndef __CRIU_ARCH_FEATURES_H
#define __CRIU_ARCH_FEATURES_H
#endif /* __CRIU_ARCH_FEATURES_H */
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
#include "restorer.h" #include "restorer.h"
#include "asm/restorer.h" #include "asm/restorer.h"
#include "asm/string.h"
#include "syscall.h" #include "syscall.h"
#include "log.h" #include "log.h"
......
#include <unistd.h> #include <unistd.h>
#include "asm/string.h"
#include "asm/types.h" #include "asm/types.h"
#include "syscall.h" #include "syscall.h"
......
#ifndef __CR_ASM_STRING_H__
#define __CR_ASM_STRING_H__
#include "common/compiler.h"
#include "asm-generic/string.h"
#endif /* __CR_ASM_STRING_H__ */
#ifndef __CRIU_ARCH_FEATURES_H
#define __CRIU_ARCH_FEATURES_H
#endif /* __CRIU_ARCH_FEATURES_H */
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
#include "restorer.h" #include "restorer.h"
#include "asm/restorer.h" #include "asm/restorer.h"
#include "asm/string.h"
#include "syscall.h" #include "syscall.h"
#include "log.h" #include "log.h"
......
#ifndef __CR_ASM_STRING_H__
#define __CR_ASM_STRING_H__
#include "common/compiler.h"
#define HAS_BUILTIN_MEMCPY
#define HAS_BUILTIN_MEMCMP
#include "asm-generic/string.h"
#ifdef CR_NOGLIBC
extern void memcpy_power7(void *to, const void *from, unsigned long n);
static inline void *builtin_memcpy(void *to, const void *from, unsigned long n)
{
if (n)
memcpy_power7(to, from, n);
return to;
}
extern int builtin_memcmp(const void *cs, const void *ct, size_t count);
#else
/*
* When building with the C library, call its services
*/
#define builtin_memcpy memcpy
#define builtin_memcmp memcmp
#endif
#endif /* __CR_ASM_STRING_H__ */
#ifndef __CRIU_ARCH_FEATURES_H
#define __CRIU_ARCH_FEATURES_H
#define ARCH_HAS_MEMCPY
#define ARCH_HAS_MEMCMP
#endif /* __CRIU_ARCH_FEATURES_H */
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#define LD ldx #define LD ldx
#endif #endif
ENTRY(builtin_memcmp) ENTRY(memcmp)
cmpdi cr1,r5,0 cmpdi cr1,r5,0
/* Use the short loop if both strings are not 8B aligned */ /* Use the short loop if both strings are not 8B aligned */
......
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
* service memcpy to initialise big local variable in the stack. * service memcpy to initialise big local variable in the stack.
*/ */
ENTRY(memcpy) ENTRY(memcpy)
ENTRY(memcpy_power7)
cmpldi r5,16 cmpldi r5,16
std r3,-STACKFRAMESIZE+STK_REG(R31)(r1) std r3,-STACKFRAMESIZE+STK_REG(R31)(r1)
blt .Lshort_copy blt .Lshort_copy
......
#include <unistd.h> #include <unistd.h>
#include <string.h>
#include "asm/string.h"
#include "asm/types.h" #include "asm/types.h"
#include "syscall.h" #include "syscall.h"
...@@ -104,7 +104,7 @@ static unsigned long put_trampoline(unsigned long at, struct vdso_symtable *sym) ...@@ -104,7 +104,7 @@ static unsigned long put_trampoline(unsigned long at, struct vdso_symtable *sym)
pr_debug("Putting vDSO trampoline in %s at %lx\n", pr_debug("Putting vDSO trampoline in %s at %lx\n",
sym->symbols[i].name, trampoline); sym->symbols[i].name, trampoline);
builtin_memcpy((void *)trampoline, &vdso_trampoline, memcpy((void *)trampoline, &vdso_trampoline,
size); size);
invalidate_caches(trampoline); invalidate_caches(trampoline);
} }
......
#ifndef __CR_ASM_STRING_H__
#define __CR_ASM_STRING_H__
#define HAS_BUILTIN_MEMCPY
#include "common/compiler.h"
#include "asm-generic/string.h"
#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)
{
if (n)
memcpy_x86(to, from, n);
return to;
}
#else
#define builtin_memcpy memcpy
#endif /* CR_NOGLIBC */
#endif /* __CR_ASM_STRING_H__ */
#ifndef __CRIU_ARCH_FEATURES_H
#define __CRIU_ARCH_FEATURES_H
#define ARCH_HAS_MEMCPY
#endif /* __CRIU_ARCH_FEATURES_H */
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
* Output: * Output:
* rax original destination * rax original destination
*/ */
ENTRY(memcpy_x86)
ENTRY(memcpy) ENTRY(memcpy)
movq %rdi, %rax movq %rdi, %rax
movq %rdx, %rcx movq %rdx, %rcx
...@@ -27,4 +26,3 @@ ENTRY(memcpy) ...@@ -27,4 +26,3 @@ ENTRY(memcpy)
rep movsb rep movsb
ret ret
END(memcpy) END(memcpy)
END(memcpy_x86)
#include <unistd.h> #include <unistd.h>
#include "asm/string.h" #include "string.h"
#include "asm/types.h" #include "asm/types.h"
#include "syscall.h" #include "syscall.h"
...@@ -41,7 +41,7 @@ int vdso_redirect_calls(unsigned long base_to, unsigned long base_from, ...@@ -41,7 +41,7 @@ int vdso_redirect_calls(unsigned long base_to, unsigned long base_from,
base_to, to->symbols[i].offset, i); base_to, to->symbols[i].offset, i);
jmp.imm64 = base_to + to->symbols[i].offset; jmp.imm64 = base_to + to->symbols[i].offset;
builtin_memcpy((void *)(base_from + from->symbols[i].offset), &jmp, sizeof(jmp)); memcpy((void *)(base_from + from->symbols[i].offset), &jmp, sizeof(jmp));
} }
return 0; return 0;
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
#include <sys/types.h> #include <sys/types.h>
#include <string.h> #include <string.h>
#include "asm/string.h"
#ifdef CONFIG_HAS_LIBBSD #ifdef CONFIG_HAS_LIBBSD
# include <bsd/string.h> # include <bsd/string.h>
...@@ -19,4 +18,6 @@ extern size_t strlcpy(char *dest, const char *src, size_t size); ...@@ -19,4 +18,6 @@ extern size_t strlcpy(char *dest, const char *src, size_t size);
extern size_t strlcat(char *dest, const char *src, size_t count); extern size_t strlcat(char *dest, const char *src, size_t count);
#endif #endif
extern int builtin_strncmp(const char *cs, const char *ct, size_t count);
#endif /* __CR_STRING_H__ */ #endif /* __CR_STRING_H__ */
...@@ -21,6 +21,7 @@ CFLAGS += -iquote $(SRC_DIR)/criu/arch/$(ARCH)/include ...@@ -21,6 +21,7 @@ CFLAGS += -iquote $(SRC_DIR)/criu/arch/$(ARCH)/include
CFLAGS += -iquote $(SRC_DIR)/criu/include CFLAGS += -iquote $(SRC_DIR)/criu/include
CFLAGS += -iquote $(SRC_DIR)/include CFLAGS += -iquote $(SRC_DIR)/include
CFLAGS += -iquote $(SRC_DIR) CFLAGS += -iquote $(SRC_DIR)
CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0
ifneq ($(filter-out ia32,$(ARCH)),) ifneq ($(filter-out ia32,$(ARCH)),)
......
lib-y += log-simple.o lib-y += log-simple.o
lib-y += util-fd.o lib-y += util-fd.o
lib-y += util.o lib-y += util.o
lib-y += string.o
ifeq ($(VDSO),y) ifeq ($(VDSO),y)
lib-y += util-vdso.o lib-y += util-vdso.o
...@@ -47,3 +48,5 @@ ifneq ($(filter-out ia32,$(ARCH)),) ...@@ -47,3 +48,5 @@ ifneq ($(filter-out ia32,$(ARCH)),)
else else
ccflags-y += -DCR_NOGLIBC -fno-pic -Wa,--noexecstack -fno-stack-protector ccflags-y += -DCR_NOGLIBC -fno-pic -Wa,--noexecstack -fno-stack-protector
endif endif
ccflags-y += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0
...@@ -672,7 +672,7 @@ static int restore_aio_ring(struct rst_aio_ring *raio) ...@@ -672,7 +672,7 @@ static int restore_aio_ring(struct rst_aio_ring *raio)
populate: populate:
i = offsetof(struct aio_ring, io_events); i = offsetof(struct aio_ring, io_events);
builtin_memcpy((void *)ctx + i, (void *)ring + i, raio->len - i); memcpy((void *)ctx + i, (void *)ring + i, raio->len - i);
/* /*
* If we failed to get the proper nr_req right and * If we failed to get the proper nr_req right and
......
#ifndef __CR_ASM_GENERIC_STRING_H__ #include <string.h>
#define __CR_ASM_GENERIC_STRING_H__ #include "features.h"
#include "common/compiler.h"
/* C compiler may generate calls to memcmp, memset, memcpy and memmove, /* C compiler may generate calls to memcmp, memset, memcpy and memmove,
* so it relies on those to be available during linking. * so it relies on those to be available during linking.
...@@ -11,27 +9,22 @@ ...@@ -11,27 +9,22 @@
* For now, not having memmove() seems OK for both gcc and clang. * For now, not having memmove() seems OK for both gcc and clang.
*/ */
#ifndef HAS_BUILTIN_MEMCPY #ifndef ARCH_HAS_MEMCPY
static __maybe_unused void *builtin_memcpy(void *to, const void *from, size_t n) void *memcpy(void *to, const void *from, size_t n)
{ {
size_t i; size_t i;
unsigned char *cto = to; unsigned char *cto = to;
const unsigned char *cfrom = from; const unsigned char *cfrom = from;
for (i = 0; i < n; ++i, ++cto, ++cfrom) { for (i = 0; i < n; ++i, ++cto, ++cfrom)
*cto = *cfrom; *cto = *cfrom;
}
return to; return to;
} }
#ifdef CR_NOGLIBC
void *memcpy(void *to, const void *from, size_t n) \
__attribute__ ((weak, alias ("builtin_memcpy")));
#endif
#endif #endif
#ifndef HAS_BUILTIN_MEMCMP #ifndef ARCH_HAS_MEMCMP
static __maybe_unused int builtin_memcmp(const void *cs, const void *ct, size_t count) int memcmp(const void *cs, const void *ct, size_t count)
{ {
const unsigned char *su1, *su2; const unsigned char *su1, *su2;
int res = 0; int res = 0;
...@@ -41,14 +34,9 @@ static __maybe_unused int builtin_memcmp(const void *cs, const void *ct, size_t ...@@ -41,14 +34,9 @@ static __maybe_unused int builtin_memcmp(const void *cs, const void *ct, size_t
break; break;
return res; return res;
} }
#ifdef CR_NOGLIBC
int memcmp(const void *cs, const void *ct, size_t count) \
__attribute__ ((weak, alias ("builtin_memcmp")));
#endif
#endif #endif
#ifndef HAS_BUILTIN_STRNCMP int builtin_strncmp(const char *cs, const char *ct, size_t count)
static always_inline int builtin_strncmp(const char *cs, const char *ct, size_t count)
{ {
size_t i; size_t i;
...@@ -60,12 +48,11 @@ static always_inline int builtin_strncmp(const char *cs, const char *ct, size_t ...@@ -60,12 +48,11 @@ static always_inline int builtin_strncmp(const char *cs, const char *ct, size_t
} }
return 0; return 0;
} }
#endif
#ifndef HAS_BUILTIN_MEMSET #ifndef ARCH_HAS_MEMSET
static __maybe_unused void *builtin_memset(void *s, const int c, size_t count) void *memset(void *s, const int c, size_t count)
{ {
volatile char *dest = s; char *dest = s;
size_t i = 0; size_t i = 0;
while (i < count) while (i < count)
...@@ -73,10 +60,4 @@ static __maybe_unused void *builtin_memset(void *s, const int c, size_t count) ...@@ -73,10 +60,4 @@ static __maybe_unused void *builtin_memset(void *s, const int c, size_t count)
return s; return s;
} }
#ifdef CR_NOGLIBC
void *memset(void *s, const int c, size_t count) \
__attribute__ ((weak, alias ("builtin_memset")));
#endif
#endif #endif
#endif /* __CR_ASM_GENERIC_STRING_H__ */
...@@ -19,8 +19,6 @@ ...@@ -19,8 +19,6 @@
# define __sys_err(ret) (-errno) # define __sys_err(ret) (-errno)
#endif #endif
#define __memcpy builtin_memcpy
#include "util-pie.h" #include "util-pie.h"
#include "fcntl.h" #include "fcntl.h"
......
...@@ -10,13 +10,20 @@ ...@@ -10,13 +10,20 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/mman.h> #include <sys/mman.h>
#include "string.h"
#include "image.h" #include "image.h"
#include "util-vdso.h" #include "util-vdso.h"
#include "vma.h" #include "vma.h"
#include "log.h" #include "log.h"
#include "common/bug.h" #include "common/bug.h"
#ifdef CR_NOGLIBC
# include "string.h"
#else
# include <string.h>
# define builtin_strncmp strncmp
#endif
#ifdef LOG_PREFIX #ifdef LOG_PREFIX
# undef LOG_PREFIX # undef LOG_PREFIX
#endif #endif
...@@ -81,7 +88,7 @@ static int has_elf_identity(Ehdr_t *ehdr) ...@@ -81,7 +88,7 @@ static int has_elf_identity(Ehdr_t *ehdr)
BUILD_BUG_ON(sizeof(elf_ident) != sizeof(ehdr->e_ident)); BUILD_BUG_ON(sizeof(elf_ident) != sizeof(ehdr->e_ident));
if (builtin_memcmp(ehdr->e_ident, elf_ident, sizeof(elf_ident))) { if (memcmp(ehdr->e_ident, elf_ident, sizeof(elf_ident))) {
pr_err("Elf header magic mismatch\n"); pr_err("Elf header magic mismatch\n");
return false; return false;
} }
...@@ -245,7 +252,7 @@ static void parse_elf_symbols(uintptr_t mem, size_t size, Phdr_t *load, ...@@ -245,7 +252,7 @@ static void parse_elf_symbols(uintptr_t mem, size_t size, Phdr_t *load,
if (builtin_strncmp(name, symbol, vdso_symbol_length)) if (builtin_strncmp(name, symbol, vdso_symbol_length))
continue; continue;
builtin_memcpy(t->symbols[i].name, name, vdso_symbol_length); memcpy(t->symbols[i].name, name, vdso_symbol_length);
t->symbols[i].offset = (unsigned long)sym->st_value - load->p_vaddr; t->symbols[i].offset = (unsigned long)sym->st_value - load->p_vaddr;
break; break;
} }
......
...@@ -2,10 +2,6 @@ ...@@ -2,10 +2,6 @@
#error "The __sys macro is required" #error "The __sys macro is required"
#endif #endif
#ifndef __memcpy
#error "The __memcpy macro is required"
#endif
static void scm_fdset_init_chunk(struct scm_fdset *fdset, int nr_fds, static void scm_fdset_init_chunk(struct scm_fdset *fdset, int nr_fds,
void *data, unsigned ch_size) void *data, unsigned ch_size)
{ {
...@@ -62,7 +58,7 @@ int send_fds(int sock, struct sockaddr_un *saddr, int len, ...@@ -62,7 +58,7 @@ int send_fds(int sock, struct sockaddr_un *saddr, int len,
for (i = 0; i < nr_fds; i += min_fd) { for (i = 0; i < nr_fds; i += min_fd) {
min_fd = min(CR_SCM_MAX_FD, nr_fds - i); min_fd = min(CR_SCM_MAX_FD, nr_fds - i);
scm_fdset_init_chunk(&fdset, min_fd, data, ch_size); scm_fdset_init_chunk(&fdset, min_fd, data, ch_size);
__memcpy(cmsg_data, &fds[i], sizeof(int) * min_fd); memcpy(cmsg_data, &fds[i], sizeof(int) * min_fd);
ret = __sys(sendmsg)(sock, &fdset.hdr, 0); ret = __sys(sendmsg)(sock, &fdset.hdr, 0);
if (ret <= 0) if (ret <= 0)
...@@ -113,7 +109,7 @@ int __recv_fds(int sock, int *fds, int nr_fds, void *data, unsigned ch_size, int ...@@ -113,7 +109,7 @@ int __recv_fds(int sock, int *fds, int nr_fds, void *data, unsigned ch_size, int
if (unlikely(min_fd <= 0)) if (unlikely(min_fd <= 0))
return -EBADFD; return -EBADFD;
__memcpy(&fds[i], cmsg_data, sizeof(int) * min_fd); memcpy(&fds[i], cmsg_data, sizeof(int) * min_fd);
if (data) if (data)
data += ch_size * min_fd; data += ch_size * min_fd;
} }
......
...@@ -22,8 +22,8 @@ COPY . /criu ...@@ -22,8 +22,8 @@ COPY . /criu
WORKDIR /criu WORKDIR /criu
RUN make mrproper RUN make mrproper
RUN make -j $(nproc) CC=$CC criu/parasite-syscall.o RUN make -j $(nproc) CC=$CC V=1 criu/parasite-syscall.o
RUN make -j $(nproc) CC=$CC RUN make -j $(nproc) CC=$CC V=1
RUN make mrproper RUN make mrproper
RUN bash -c 'CLEAN="$(git clean -ndx --exclude=scripts/build --exclude=.config)"; echo "${CLEAN}"; test -z "${CLEAN}"; exit $?' RUN bash -c 'CLEAN="$(git clean -ndx --exclude=scripts/build --exclude=.config)"; echo "${CLEAN}"; test -z "${CLEAN}"; exit $?'
RUN make -j $(nproc) CC=$CC -C test/zdtm RUN make -j $(nproc) CC=$CC -C test/zdtm
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment