[CRIU] [PATCH 05/19] compel: plusings -- Add std plugin

Cyrill Gorcunov gorcunov at openvz.org
Wed Sep 21 13:54:20 PDT 2016


The plugin provides basic features as
string copying, syscalls, printing.
Not used on its own by now but will
be shipping by default with other
plugins.

With great help from Dmitry Safonov.

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 .../x86/plugins/include/asm/std/syscall-types.h    |  53 +++++
 compel/arch/x86/plugins/std/call32.S               |  71 ++++++
 .../plugins/std/syscalls/syscall-common-x86-32.S   |  36 +++
 .../plugins/std/syscalls/syscall-common-x86-64.S   |  21 ++
 compel/arch/x86/plugins/std/syscalls/syscall32.c   |  85 +++++++
 .../arch/x86/plugins/std/syscalls/syscall_32.tbl   |  94 ++++++++
 .../arch/x86/plugins/std/syscalls/syscall_64.tbl   | 105 +++++++++
 compel/arch/x86/scripts/pack.lds.S                 |  30 +++
 compel/plugins/Makefile                            | 127 ++++++++++
 compel/plugins/include/uapi/plugin-std.h           |   6 +
 compel/plugins/include/uapi/std/string.h           |  28 +++
 compel/plugins/include/uapi/std/syscall-types.h    |  55 +++++
 compel/plugins/std/std.c                           |  89 +++++++
 compel/plugins/std/string.c                        | 262 +++++++++++++++++++++
 14 files changed, 1062 insertions(+)
 create mode 100644 compel/arch/x86/plugins/include/asm/std/syscall-types.h
 create mode 100644 compel/arch/x86/plugins/std/call32.S
 create mode 100644 compel/arch/x86/plugins/std/syscalls/syscall-common-x86-32.S
 create mode 100644 compel/arch/x86/plugins/std/syscalls/syscall-common-x86-64.S
 create mode 100644 compel/arch/x86/plugins/std/syscalls/syscall32.c
 create mode 100644 compel/arch/x86/plugins/std/syscalls/syscall_32.tbl
 create mode 100644 compel/arch/x86/plugins/std/syscalls/syscall_64.tbl
 create mode 100644 compel/arch/x86/scripts/pack.lds.S
 create mode 100644 compel/plugins/Makefile
 create mode 100644 compel/plugins/include/uapi/plugin-std.h
 create mode 100644 compel/plugins/include/uapi/std/string.h
 create mode 100644 compel/plugins/include/uapi/std/syscall-types.h
 create mode 100644 compel/plugins/std/std.c
 create mode 100644 compel/plugins/std/string.c

diff --git a/compel/arch/x86/plugins/include/asm/std/syscall-types.h b/compel/arch/x86/plugins/include/asm/std/syscall-types.h
new file mode 100644
index 000000000000..744809d07894
--- /dev/null
+++ b/compel/arch/x86/plugins/include/asm/std/syscall-types.h
@@ -0,0 +1,53 @@
+#ifndef COMPEL_ARCH_SYSCALL_TYPES_H__
+#define COMPEL_ARCH_SYSCALL_TYPES_H__
+
+/* Types for sigaction, sigprocmask syscalls */
+typedef void rt_signalfn_t(int, siginfo_t *, void *);
+typedef rt_signalfn_t *rt_sighandler_t;
+
+typedef void rt_restorefn_t(void);
+typedef rt_restorefn_t *rt_sigrestore_t;
+
+#define _KNSIG           64
+# define _NSIG_BPW      64
+
+#define _KNSIG_WORDS     (_KNSIG / _NSIG_BPW)
+
+typedef struct {
+	u64 sig[_KNSIG_WORDS];
+} k_rtsigset_t;
+
+typedef struct {
+	rt_sighandler_t	rt_sa_handler;
+	unsigned long	rt_sa_flags;
+	rt_sigrestore_t	rt_sa_restorer;
+	k_rtsigset_t	rt_sa_mask;
+} rt_sigaction_t;
+
+/*
+ * Note: there is unaligned access on x86_64 and it's fine.
+ * However, when porting this code -- keep in mind about possible issues
+ * with unaligned rt_sa_mask.
+ */
+typedef struct __attribute__((packed)) {
+	u32	rt_sa_handler;
+	u32	rt_sa_flags;
+	u32	rt_sa_restorer;
+	k_rtsigset_t	rt_sa_mask;
+} rt_sigaction_t_compat;
+
+/* Types for set_thread_area, get_thread_area syscalls */
+typedef struct {
+	unsigned int	entry_number;
+	unsigned int	base_addr;
+	unsigned int	limit;
+	unsigned int	seg_32bit:1;
+	unsigned int	contents:2;
+	unsigned int	read_exec_only:1;
+	unsigned int	limit_in_pages:1;
+	unsigned int	seg_not_present:1;
+	unsigned int	useable:1;
+	unsigned int	lm:1;
+} user_desc_t;
+
+#endif /* COMPEL_ARCH_SYSCALL_TYPES_H__ */
diff --git a/compel/arch/x86/plugins/std/call32.S b/compel/arch/x86/plugins/std/call32.S
new file mode 100644
index 000000000000..935461dcdc86
--- /dev/null
+++ b/compel/arch/x86/plugins/std/call32.S
@@ -0,0 +1,71 @@
+/*
+ * call32.S - assembly helpers for mixed-bitness code
+ * From kernel selftests originally: tools/testing/selftests/x86/thunks.S
+ * Copyright (c) 2015 Andrew Lutomirski
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * These are little helpers that make it easier to switch bitness on
+ * the fly.
+ */
+
+#include "asm/linkage.h"
+
+#define __USER32_CS	0x23
+#define __USER_CS	0x33
+
+	.text
+
+/*
+ * @rdi: Stack to use
+ * @esi: Pointer to function for calling
+ */
+ENTRY(call32_from_64)
+	/* Callee-saving registers due to ABI */
+	pushq %rbx
+	pushq %rbp
+	pushq %r12
+	pushq %r13
+	pushq %r14
+	pushq %r15
+	pushfq
+
+	/* Switch stacks */
+	sub $8, %rdi
+	mov %rsp,(%rdi)
+	mov %rdi,%rsp
+
+	/* Switch into compatibility mode */
+	pushq $__USER32_CS
+	pushq $1f
+	lretq
+
+1:
+	.code32
+	/* Run function and switch back */
+	call *%esi
+	jmp $__USER_CS,$1f
+	.code64
+
+1:
+	/* Restore the stack */
+	mov (%rsp),%rsp
+	add $8, %rdi
+
+	/* Restore registers */
+	popfq
+	popq %r15
+	popq %r14
+	popq %r13
+	popq %r12
+	popq %rbp
+	popq %rbx
+	ret
+END(call32_from_64)
diff --git a/compel/arch/x86/plugins/std/syscalls/syscall-common-x86-32.S b/compel/arch/x86/plugins/std/syscalls/syscall-common-x86-32.S
new file mode 100644
index 000000000000..ae6d594dc4fe
--- /dev/null
+++ b/compel/arch/x86/plugins/std/syscalls/syscall-common-x86-32.S
@@ -0,0 +1,36 @@
+#include "asm/linkage.h"
+
+#define SYSCALL(name, opcode)		\
+	ENTRY(name);			\
+	movl	$opcode, %eax;		\
+	jmp	__syscall_common;	\
+	END(name)
+
+ENTRY(__syscall_common)
+	pushl	%ebx
+	pushl	%esi
+	pushl	%edi
+	pushl	%ebp
+
+#define __arg(n)	(4 * (n) + 20)(%esp)
+	movl	__arg(0),%ebx
+	movl	__arg(1),%ecx
+	movl	__arg(2),%edx
+	movl	__arg(3),%esi
+	movl	__arg(4),%edi
+	movl	__arg(5),%ebp
+#undef __arg
+
+	int	$0x80
+
+	popl	%ebp
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	ret
+END(__syscall_common)
+
+ENTRY(__cr_restore_rt)
+	movl	$__NR_rt_sigreturn, %eax
+	jmp	__syscall_common
+END(__cr_restore_rt)
diff --git a/compel/arch/x86/plugins/std/syscalls/syscall-common-x86-64.S b/compel/arch/x86/plugins/std/syscalls/syscall-common-x86-64.S
new file mode 100644
index 000000000000..b93c31288a20
--- /dev/null
+++ b/compel/arch/x86/plugins/std/syscalls/syscall-common-x86-64.S
@@ -0,0 +1,21 @@
+#include "asm/linkage.h"
+
+#define SYSCALL(name, opcode)		\
+	ENTRY(name);			\
+	movl	$opcode, %eax;		\
+	jmp	__syscall_common;	\
+	END(name)
+
+	.text
+	.align	4
+
+ENTRY(__syscall_common)
+	movq	%rcx, %r10
+	syscall
+	ret
+END(__syscall_common)
+
+ENTRY(__cr_restore_rt)
+	movq $__NR_rt_sigreturn, %rax
+	syscall
+END(__cr_restore_rt)
diff --git a/compel/arch/x86/plugins/std/syscalls/syscall32.c b/compel/arch/x86/plugins/std/syscalls/syscall32.c
new file mode 100644
index 000000000000..88af59330adf
--- /dev/null
+++ b/compel/arch/x86/plugins/std/syscalls/syscall32.c
@@ -0,0 +1,85 @@
+#include "asm/types.h"
+#include "syscall-32.h"
+
+#define SYS_SOCKET	1		/* sys_socket(2)		*/
+#define SYS_BIND	2		/* sys_bind(2)			*/
+#define SYS_CONNECT	3		/* sys_connect(2)		*/
+#define SYS_SENDTO	11		/* sys_sendto(2)		*/
+#define SYS_RECVFROM	12		/* sys_recvfrom(2)		*/
+#define SYS_SHUTDOWN	13		/* sys_shutdown(2)		*/
+#define SYS_SETSOCKOPT	14		/* sys_setsockopt(2)		*/
+#define SYS_GETSOCKOPT	15		/* sys_getsockopt(2)		*/
+#define SYS_SENDMSG	16		/* sys_sendmsg(2)		*/
+#define SYS_RECVMSG	17		/* sys_recvmsg(2)		*/
+
+long sys_socket(int domain, int type, int protocol)
+{
+	u32 a[] = { (u32)domain, (u32)type, (u32)protocol };
+	return sys_socketcall(SYS_SOCKET, (unsigned long *)a);
+}
+
+long sys_connect(int sockfd, struct sockaddr *addr, int addrlen)
+{
+	u32 a[] = {(u32)sockfd, (u32)addr, (u32)addrlen};
+	return sys_socketcall(SYS_CONNECT, (unsigned long *)a);
+}
+
+long sys_sendto(int sockfd, void *buff, size_t len, unsigned int flags, struct sockaddr *addr, int addr_len)
+{
+	u32 a[] = {(u32)sockfd, (u32)buff, (u32)len, (u32)flags, (u32)addr, (u32)addr_len};
+	return sys_socketcall(SYS_SENDTO, (unsigned long *)a);
+}
+
+long sys_recvfrom(int sockfd, void *ubuf, size_t size, unsigned int flags, struct sockaddr *addr, int *addr_len)
+{
+	u32 a[] = {(u32)sockfd, (u32)ubuf, (u32)size, (u32)flags, (u32)addr, (u32)addr_len};
+	return sys_socketcall(SYS_RECVFROM, (unsigned long *)a);
+}
+
+long sys_sendmsg(int sockfd, const struct msghdr *msg, int flags)
+{
+	u32 a[] = {(u32)sockfd, (u32)msg, (u32)flags};
+	return sys_socketcall(SYS_SENDMSG, (unsigned long *)a);
+}
+
+long sys_recvmsg(int sockfd, struct msghdr *msg, int flags)
+{
+	u32 a[] = {(u32)sockfd, (u32)msg, (u32)flags};
+	return sys_socketcall(SYS_RECVMSG, (unsigned long *)a);
+}
+
+long sys_shutdown(int sockfd, int how)
+{
+	u32 a[] = {(u32)sockfd, (u32)how};
+	return sys_socketcall(SYS_SHUTDOWN, (unsigned long *)a);
+}
+
+long sys_bind(int sockfd, const struct sockaddr *addr, int addrlen)
+{
+	u32 a[] = {(u32)sockfd, (u32)addr, (u32)addrlen};
+	return sys_socketcall(SYS_BIND, (unsigned long *)a);
+}
+
+long sys_setsockopt(int sockfd, int level, int optname, const void *optval, unsigned int optlen)
+{
+	u32 a[] = {(u32)sockfd, (u32)level, (u32)optname, (u32)optval, (u32)optlen};
+	return sys_socketcall(SYS_SETSOCKOPT, (unsigned long *)a);
+}
+
+long sys_getsockopt(int sockfd, int level, int optname, const void *optval, unsigned int *optlen)
+{
+	u32 a[] = {(u32)sockfd, (u32)level, (u32)optname, (u32)optval, (u32)optlen};
+	return sys_socketcall(SYS_GETSOCKOPT, (unsigned long *)a);
+}
+
+#define SHMAT		21
+
+long sys_shmat(int shmid, void *shmaddr, int shmflag)
+{
+	return sys_ipc(SHMAT, shmid, shmflag, 0, shmaddr, 0);
+}
+
+long sys_pread(unsigned int fd, char *ubuf, u32 count, u64 pos)
+{
+	return sys_pread64(fd, ubuf, count, (u32)(pos & 0xffffffffu), (u32)(pos >> 32));
+}
diff --git a/compel/arch/x86/plugins/std/syscalls/syscall_32.tbl b/compel/arch/x86/plugins/std/syscalls/syscall_32.tbl
new file mode 100644
index 000000000000..7c4867c1b3f5
--- /dev/null
+++ b/compel/arch/x86/plugins/std/syscalls/syscall_32.tbl
@@ -0,0 +1,94 @@
+#
+# System calls table, please make sure the table consist only the syscalls
+# really used somewhere in project.
+#
+# code		name			arguments
+# -------------------------------------------------------------------------------------------------------------------------------------------------------------
+__NR_restart_syscall	0		sys_restart_syscall	(void)
+__NR_exit		1		sys_exit		(unsigned long error_code)
+__NR_read		3		sys_read		(int fd, void *buf, unsigned long count)
+__NR_write		4		sys_write		(int fd, const void *buf, unsigned long count)
+__NR_open		5		sys_open		(const char *filename, int flags, unsigned int mode)
+__NR_close		6		sys_close		(int fd)
+__NR_unlink		10		sys_unlink		(char *pathname)
+__NR_lseek		19		sys_lseek		(int fd, s32 offset, unsigned int origin)
+__NR_getpid		20		sys_getpid		(void)
+__NR_mount		21		sys_mount		(const char *dev_name, const char *dir_name, const char *type, unsigned long flags, const void *data)
+__NR_ptrace		26		sys_ptrace		(long request, pid_t pid, void *addr, void *data)
+__NR_kill		37		sys_kill		(long pid, int sig)
+__NR_mkdir		39		sys_mkdir		(const char *name, int mode)
+__NR_rmdir		40		sys_rmdir		(const char *name)
+__NR_brk		45		sys_brk			(void *addr)
+__NR_umount2		52		sys_umount2		(char *name, int flags)
+__NR_ioctl		54		sys_ioctl		(unsigned int fd, unsigned int cmd, unsigned long arg)
+__NR_fcntl		55		sys_fcntl		(unsigned int fd, unsigned int cmd, unsigned long arg)
+__NR_umask		60		sys_umask		(int mask)
+__NR_setrlimit		75		sys_setrlimit		(unsigned int resource, struct krlimit *rlim)
+__NR_munmap		91		sys_munmap		(void *addr, unsigned long len)
+__NR_setpriority	97		sys_setpriority		(int which, int who, int nice)
+__NR_socketcall		102		sys_socketcall		(int call, unsigned long *args)
+__NR_setitimer		104		sys_setitimer		(int which, struct itimerval *in, struct itimerval *out)
+__NR_getitimer		105		sys_getitimer		(int which, struct itimerval *it)
+__NR_wait4		114		sys_wait4		(pid_t pid, int *stat_addr, int options, struct rusage *ru)
+__NR_ipc		117		sys_ipc			(unsigned int call, int first, unsigned long second, unsigned long third, void *ptr, long fifth)
+__NR_clone		120		sys_clone		(unsigned long flags, void *child_stack, void *parent_tid, void *child_tid)
+__NR_mprotect		125		sys_mprotect		(const void *addr, unsigned long len, unsigned long prot)
+__NR_getpgid		132		sys_getpgid		(pid_t pid)
+__NR_personality	136		sys_personality		(unsigned int personality)
+__NR_flock		143		sys_flock		(int fd, unsigned long cmd)
+__NR_getsid		147		sys_getsid		(void)
+__NR_sched_setscheduler	156		sys_sched_setscheduler	(int pid, int policy, struct sched_param *p)
+__NR_nanosleep		162		sys_nanosleep		(struct timespec *rqtp, struct timespec *rmtp)
+__NR_mremap		163		sys_mremap		(unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags, unsigned long new_addr)
+__NR_prctl		172		sys_prctl		(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5)
+__NR_rt_sigreturn	173		sys_rt_sigreturn	(void)
+__NR_rt_sigaction	174		sys_sigaction		(int signum, const rt_sigaction_t *act, rt_sigaction_t *oldact, size_t sigsetsize)
+__NR_rt_sigprocmask	175		sys_sigprocmask		(int how, k_rtsigset_t *set, k_rtsigset_t *oset, size_t sigsetsize)
+__NR_rt_sigqueueinfo	178		sys_rt_sigqueueinfo	(pid_t pid, int sig, siginfo_t *uinfo)
+__NR_pread64		180		sys_pread64		(unsigned int fd, char *ubuf, u32 count, u32 poslo, u32 poshi)
+__NR_capget		184		sys_capget		(struct cap_header *h, struct cap_data *d)
+__NR_capset		185		sys_capset		(struct cap_header *h, struct cap_data *d)
+__NR_sigaltstack	186		sys_sigaltstack		(const void *uss_ptr, void *uoss_ptr)
+__NR_mmap2		192		sys_mmap		(void *addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff)
+__NR_getgroups32	205		sys_getgroups		(int gsize, unsigned int *groups)
+__NR_setgroups32	206		sys_setgroups		(int gsize, unsigned int *groups)
+__NR_setresuid32	208		sys_setresuid		(int uid, int euid, int suid)
+__NR_getresuid32	209		sys_getresuid		(int *uid, int *euid, int *suid)
+__NR_setresgid32	210		sys_setresgid		(int gid, int egid, int sgid)
+__NR_getresgid32	211		sys_getresgid		(int *gid, int *egid, int *sgid)
+__NR_setfsuid32		215		sys_setfsuid		(int fsuid)
+__NR_setfsgid32		216		sys_setfsgid		(int fsgid)
+__NR_mincore		218		sys_mincore		(void *addr, unsigned long size, unsigned char *vec)
+__NR_madvise		219		sys_madvise		(unsigned long start, size_t len, int behavior)
+__NR_gettid		224		sys_gettid		(void)
+__NR_futex		240		sys_futex		(u32 *uaddr, int op, u32 val, struct timespec *utime, u32 *uaddr2, u32 val3)
+__NR_set_thread_area	243		sys_set_thread_area	(user_desc_t *info)
+__NR_get_thread_area	244		sys_get_thread_area	(user_desc_t *info)
+__NR_io_setup		245		sys_io_setup		(unsigned nr_reqs, aio_context_t *ctx32p)
+__NR_io_getevents	247		sys_io_getevents	(aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct timespec *timeout)
+__NR_io_submit		248		sys_io_submit		(aio_context_t ctx_id, long nr, struct iocb **iocbpp)
+__NR_exit_group		252		sys_exit_group		(int error_code)
+__NR_set_tid_address	258		sys_set_tid_address	(int *tid_addr)
+__NR_timer_create	259		sys_timer_create	(clockid_t which_clock, struct sigevent *timer_event_spec, kernel_timer_t *created_timer_id)
+__NR_timer_settime	260		sys_timer_settime	(kernel_timer_t timer_id, int flags, struct itimerspec *new, struct itimerspec *old)
+__NR_timer_gettime	261		sys_timer_gettime	(int timer_id, struct itimerspec *setting)
+__NR_timer_getoverrun	262		sys_timer_getoverrun	(int timer_id)
+__NR_timer_delete	263		sys_timer_delete	(kernel_timer_t timer_id)
+__NR_clock_gettime	265		sys_clock_gettime	(int which_clock, struct timespec *tp)
+__NR_waitid		284		sys_waitid		(int which, pid_t pid, struct siginfo *infop, int options, struct rusage *ru)
+__NR_openat		295		sys_openat		(int dfd, const char *filename, int flags, int mode)
+__NR_readlinkat		305		sys_readlinkat		(int fd, const char *path, char *buf, int bufsize)
+__NR_set_robust_list	311		sys_set_robust_list	(struct robust_list_head *head, size_t len)
+__NR_get_robust_list	312		sys_get_robust_list	(int pid, struct robust_list_head **head_ptr, size_t *len_ptr)
+__NR_vmsplice		316		sys_vmsplice		(int fd, const struct iovec *iov, unsigned int nr_segs, unsigned int flags)
+__NR_signalfd		321		sys_signalfd		(int ufd, const k_rtsigset_t *sigmask, size_t sigsetsize)
+__NR_timerfd_settime	325		sys_timerfd_settime	(int ufd, int flags, const struct itimerspec *utmr, struct itimerspec *otmr)
+__NR_rt_tgsigqueueinfo	335		sys_rt_tgsigqueueinfo	(pid_t tgid, pid_t pid, int sig, siginfo_t *uinfo)
+__NR_fanotify_init	338		sys_fanotify_init	(unsigned int flags, unsigned int event_f_flags)
+__NR_fanotify_mark	339		sys_fanotify_mark	(int fanotify_fd, unsigned int flag, u32 mask, int dfd, const char *pathname)
+__NR_open_by_handle_at	342		sys_open_by_handle_at	(int mountdirfd, struct file_handle *handle, int flags)
+__NR_setns		346		sys_setns		(int fd, int nstype)
+__NR_kcmp		349		sys_kcmp		(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2)
+__NR_seccomp		354		sys_seccomp		(unsigned int op, unsigned int flags, const char *uargs)
+__NR_memfd_create	356		sys_memfd_create	(const char *name, unsigned int flags)
+__NR_userfaultfd	374		sys_userfaultfd		(int flags)
diff --git a/compel/arch/x86/plugins/std/syscalls/syscall_64.tbl b/compel/arch/x86/plugins/std/syscalls/syscall_64.tbl
new file mode 100644
index 000000000000..285874938b38
--- /dev/null
+++ b/compel/arch/x86/plugins/std/syscalls/syscall_64.tbl
@@ -0,0 +1,105 @@
+#
+# System calls table, please make sure the table consist only the syscalls
+# really used somewhere in project.
+#
+# __NR_name			code		name			arguments
+# -------------------------------------------------------------------------------------------------------------------------------------------------------------
+__NR_read			0		sys_read		(int fd, void *buf, unsigned long count)
+__NR_write			1		sys_write		(int fd, const void *buf, unsigned long count)
+__NR_open			2		sys_open		(const char *filename, unsigned long flags, unsigned long mode)
+__NR_close			3		sys_close		(int fd)
+__NR_lseek			8		sys_lseek		(int fd, unsigned long offset, unsigned long origin)
+__NR_mmap			9		sys_mmap		(void *addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long offset)
+__NR_mprotect			10		sys_mprotect		(const void *addr, unsigned long len, unsigned long prot)
+__NR_munmap			11		sys_munmap		(void *addr, unsigned long len)
+__NR_brk			12		sys_brk			(void *addr)
+__NR_rt_sigaction		13		sys_sigaction		(int signum, const rt_sigaction_t *act, rt_sigaction_t *oldact, size_t sigsetsize)
+__NR_rt_sigprocmask		14		sys_sigprocmask		(int how, k_rtsigset_t *set, k_rtsigset_t *old, size_t sigsetsize)
+__NR_rt_sigreturn		15		sys_rt_sigreturn	(void)
+__NR_ioctl			16		sys_ioctl		(unsigned int fd, unsigned int cmd, unsigned long arg)
+__NR_pread64			17		sys_pread		(unsigned int fd, char *buf, size_t count, loff_t pos)
+__NR_mremap			25		sys_mremap		(unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags, unsigned long new_addr)
+__NR_mincore			27		sys_mincore		(void *addr, unsigned long size, unsigned char *vec)
+__NR_madvise			28		sys_madvise		(unsigned long start, size_t len, int behavior)
+__NR_shmat			30		sys_shmat		(int shmid, void *shmaddr, int shmflag)
+__NR_dup2			33		sys_dup2		(int oldfd, int newfd)
+__NR_nanosleep			35		sys_nanosleep		(struct timespec *req, struct timespec *rem)
+__NR_getitimer			36		sys_getitimer		(int which, const struct itimerval *val)
+__NR_setitimer			38		sys_setitimer		(int which, const struct itimerval *val, struct itimerval *old)
+__NR_getpid			39		sys_getpid		(void)
+__NR_socket			41		sys_socket		(int domain, int type, int protocol)
+__NR_connect			42		sys_connect		(int sockfd, struct sockaddr *addr, int addrlen)
+__NR_sendto			44		sys_sendto		(int sockfd, void *buff, size_t len, unsigned int flags, struct sockaddr *addr, int addr_len)
+__NR_recvfrom			45		sys_recvfrom		(int sockfd, void *ubuf, size_t size, unsigned int flags, struct sockaddr *addr, int *addr_len)
+__NR_sendmsg			46		sys_sendmsg		(int sockfd, const struct msghdr *msg, int flags)
+__NR_recvmsg			47		sys_recvmsg		(int sockfd, struct msghdr *msg, int flags)
+__NR_shutdown			48		sys_shutdown		(int sockfd, int how)
+__NR_bind			49		sys_bind		(int sockfd, const struct sockaddr *addr, int addrlen)
+__NR_setsockopt			54		sys_setsockopt		(int sockfd, int level, int optname, const void *optval, socklen_t optlen)
+__NR_getsockopt			55		sys_getsockopt		(int sockfd, int level, int optname, const void *optval, socklen_t *optlen)
+__NR_clone			56		sys_clone		(unsigned long flags, void *child_stack, void *parent_tid, void *child_tid)
+__NR_exit			60		sys_exit		(unsigned long error_code)
+__NR_wait4			61		sys_wait4		(int pid, int *status, int options, struct rusage *ru)
+__NR_kill			62		sys_kill		(long pid, int sig)
+__NR_fcntl			72		sys_fcntl		(int fd, int type, long arg)
+__NR_flock			73		sys_flock		(int fd, unsigned long cmd)
+__NR_mkdir			83		sys_mkdir		(const char *name, int mode)
+__NR_rmdir			84		sys_rmdir		(const char *name)
+__NR_unlink			87		sys_unlink		(char *pathname)
+__NR_umask			95		sys_umask		(int mask)
+__NR_ptrace			101		sys_ptrace		(long request, pid_t pid, void *addr, void *data)
+__NR_getgroups			115		sys_getgroups		(int gsize, unsigned int *groups)
+__NR_setgroups			116		sys_setgroups		(int gsize, unsigned int *groups)
+__NR_setresuid			117		sys_setresuid		(int uid, int euid, int suid)
+__NR_getresuid			118		sys_getresuid		(int *uid, int *euid, int *suid)
+__NR_setresgid			119		sys_setresgid		(int gid, int egid, int sgid)
+__NR_getresgid			120		sys_getresgid		(int *gid, int *egid, int *sgid)
+__NR_getpgid			121		sys_getpgid		(pid_t pid)
+__NR_setfsuid			122		sys_setfsuid		(int fsuid)
+__NR_setfsgid			123		sys_setfsgid		(int fsgid)
+__NR_getsid			124		sys_getsid		(void)
+__NR_capget			125		sys_capget		(struct cap_header *h, struct cap_data *d)
+__NR_capset			126		sys_capset		(struct cap_header *h, struct cap_data *d)
+__NR_rt_sigqueueinfo		129		sys_rt_sigqueueinfo	(pid_t pid, int sig, siginfo_t *info)
+__NR_sigaltstack		131		sys_sigaltstack		(const void *uss, void *uoss)
+__NR_personality		135		sys_personality		(unsigned int personality)
+__NR_setpriority		141		sys_setpriority		(int which, int who, int nice)
+__NR_sched_setscheduler		144		sys_sched_setscheduler	(int pid, int policy, struct sched_param *p)
+__NR_prctl			157		sys_prctl		(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5)
+__NR_arch_prctl			158		sys_arch_prctl		(int option, unsigned long addr)
+__NR_setrlimit			160		sys_setrlimit		(int resource, struct krlimit *rlim)
+__NR_mount			165		sys_mount		(char *dev_nmae, char *dir_name, char *type, unsigned long flags, void *data)
+__NR_umount2			166		sys_umount2		(char *name, int flags)
+__NR_gettid			186		sys_gettid		(void)
+__NR_futex			202		sys_futex		(u32 *uaddr, int op, u32 val, struct timespec *utime, u32 *uaddr2, u32 val3)
+__NR_set_thread_area		205		sys_set_thread_area	(user_desc_t *info)
+__NR_io_setup			206		sys_io_setup		(unsigned nr_events, aio_context_t *ctx)
+__NR_io_getevents		208		sys_io_getevents	(aio_context_t ctx, long min_nr, long nr, struct io_event *evs, struct timespec *tmo)
+__NR_io_submit			209		sys_io_submit		(aio_context_t ctx, long nr, struct iocb **iocbpp)
+__NR_get_thread_area		211		sys_get_thread_area	(user_desc_t *info)
+__NR_set_tid_address		218		sys_set_tid_address	(int *tid_addr)
+__NR_restart_syscall		219		sys_restart_syscall	(void)
+__NR_sys_timer_create		222		sys_timer_create	(clockid_t which_clock, struct sigevent *timer_event_spec, kernel_timer_t *created_timer_id)
+__NR_sys_timer_settime		223		sys_timer_settime	(kernel_timer_t timer_id, int flags, const struct itimerspec *new_setting, struct itimerspec *old_setting)
+__NR_sys_timer_gettime		224		sys_timer_gettime	(int timer_id, const struct itimerspec *setting)
+__NR_sys_timer_getoverrun	225		sys_timer_getoverrun	(int timer_id)
+__NR_sys_timer_delete		226		sys_timer_delete	(kernel_timer_t timer_id)
+__NR_clock_gettime		228		sys_clock_gettime	(const clockid_t which_clock, const struct timespec *tp)
+__NR_exit_group			231		sys_exit_group		(int error_code)
+__NR_openat			257		sys_openat		(int dfd, const char *filename, int flags, int mode)
+__NR_waitid			247		sys_waitid		(int which, pid_t pid, struct siginfo *infop, int options, struct rusage *ru)
+__NR_readlinkat			267		sys_readlinkat		(int fd, const char *path, char *buf, int bufsize)
+__NR_set_robust_list		273		sys_set_robust_list	(struct robust_list_head *head, size_t len)
+__NR_get_robust_list		274		sys_get_robust_list	(int pid, struct robust_list_head **head_ptr, size_t *len_ptr)
+__NR_seccomp			317		sys_seccomp		(unsigned int op, unsigned int flags, const char *uargs)
+__NR_vmsplice			278		sys_vmsplice		(int fd, const struct iovec *iov, unsigned long nr_segs, unsigned int flags)
+__NR_timerfd_settime		286		sys_timerfd_settime	(int ufd, int flags, const struct itimerspec *utmr, struct itimerspec *otmr)
+__NR_signalfd4			289		sys_signalfd		(int fd, k_rtsigset_t *mask, size_t sizemask, int flags)
+__NR_rt_tgsigqueueinfo		297		sys_rt_tgsigqueueinfo	(pid_t tgid, pid_t pid, int sig, siginfo_t *info)
+__NR_fanotify_init		300		sys_fanotify_init	(unsigned int flags, unsigned int event_f_flags)
+__NR_fanotify_mark		301		sys_fanotify_mark	(int fanotify_fd, unsigned int flags, u64 mask, int dfd, const char *pathname)
+__NR_open_by_handle_at		304		sys_open_by_handle_at	(int mountdirfd, struct file_handle *handle, int flags)
+__NR_setns			308		sys_setns		(int fd, int nstype)
+__NR_kcmp			312		sys_kcmp		(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2)
+__NR_memfd_create		319		sys_memfd_create	(const char *name, unsigned int flags)
+__NR_userfaultfd		323		sys_userfaultfd		(int flags)
diff --git a/compel/arch/x86/scripts/pack.lds.S b/compel/arch/x86/scripts/pack.lds.S
new file mode 100644
index 000000000000..3b94b3ecd2f2
--- /dev/null
+++ b/compel/arch/x86/scripts/pack.lds.S
@@ -0,0 +1,30 @@
+OUTPUT_ARCH(i386:x86-64)
+SECTIONS
+{
+	. = ALIGN(64);
+	.text : {
+		*(.compel.prologue.text)
+		*(.text*)
+	} =0x0
+
+	. = ALIGN(64);
+	.compel.init : {
+		*(.compel.init)
+	} =0xff
+
+	. = ALIGN(64);
+	.data : {
+		*(.data*)
+		*(.bss*)
+		*(.rodata*)
+	} =0x0
+
+	/DISCARD/ : {
+		*(.debug*)
+		*(.comment*)
+		*(.note*)
+		*(.group*)
+		*(.eh_frame*)
+		*(*)
+	}
+}
diff --git a/compel/plugins/Makefile b/compel/plugins/Makefile
new file mode 100644
index 000000000000..f0b1de802368
--- /dev/null
+++ b/compel/plugins/Makefile
@@ -0,0 +1,127 @@
+.PHONY: .FORCE
+
+ARCH_DIR		:= compel/arch/$(ARCH)/plugins
+
+ccflags-y		+= -iquote $(obj)/include/
+ccflags-y		+= -iquote $(obj)/include/uapi
+ccflags-y		+= -iquote $(SRC_DIR)/criu/include
+ccflags-y		+= -iquote $(SRC_DIR)/criu/arch/$(ARCH)/include
+ccflags-y		+= -iquote $(SRC_DIR)/compel/include
+ccflags-y		+= -iquote $(SRC_DIR)/$(ARCH_DIR)/include
+
+asflags-y		+= -iquote $(SRC_DIR)/criu/arch/$(ARCH)/include
+asflags-y		+= -iquote $(SRC_DIR)/compel/plugins/include/uapi
+asflags-y		+= -iquote $(SRC_DIR)/$(ARCH_DIR)
+
+#
+# STD plugin
+target			+= std
+std-obj-y		+= std/std.o
+std-obj-y		+= std/string.o
+std-obj-y		+= arch/$(ARCH)/plugins/std/syscalls-64.o
+std-obj-y		+= arch/$(ARCH)/plugins/std/calls32.o
+
+sys-proto-generic	:= $(obj)/include/uapi/std/syscall.h
+sys-codes-generic	:= $(obj)/include/uapi/std/syscall-codes.h
+sys-codes		 = $(obj)/include/uapi/std/syscall-codes-$(1).h
+sys-proto		 = $(obj)/include/uapi/std/syscall-$(1).h
+sys-def			 = $(ARCH_DIR)/std/syscalls/syscall_$(1).tbl
+sys-asm			 = $(ARCH_DIR)/std/syscalls-$(1).S
+sys-asm-common-name	 = std/syscalls/syscall-common-x86-$(1).S
+sys-asm-common		 = $(ARCH_DIR)/$(sys-asm-common-name)
+
+sys-bits		:= 64
+
+AV			:= $$$$
+
+define gen-rule-sys-codes
+$(sys-codes): $(sys-def)
+	$(call msg-gen, $$@)
+	$(Q) echo "/* Autogenerated, don't edit */"					>  $$@
+	$(Q) echo "#ifndef ASM_SYSCALL_CODES_H_$(1)__"					>> $$@
+	$(Q) echo "#define ASM_SYSCALL_CODES_H_$(1)__"					>> $$@
+	$(Q) cat $$< | awk '/^__NR/{SYSN=$(AV)1;					\
+		sub("^__NR", "SYS", SYSN);						\
+		print "\n#ifndef ", $(AV)1;						\
+		print "#define", $(AV)1, $(AV)2;					\
+		print "#endif";								\
+		print "\n#ifndef ", SYSN;						\
+		print "#define ", SYSN, $(AV)1;						\
+		print "#endif";}'							>> $$@
+	$(Q) echo "#endif /* ASM_SYSCALL_CODES_H_$(1)__ */"				>> $$@
+endef
+
+define gen-rule-sys-proto
+$(sys-proto): $(sys-def)
+	$(call msg-gen, $$@)
+	$(Q) echo "/* Autogenerated, don't edit */"					>  $$@
+	$(Q) echo "#ifndef ASM_SYSCALL_PROTO_H_$(1)__"					>> $$@
+	$(Q) echo "#define ASM_SYSCALL_PROTO_H_$(1)__"					>> $$@
+	$(Q) echo '#include "std/syscall-codes-$(1).h"'					>> $$@
+	$(Q) echo '#include "syscall-types.h"'						>> $$@
+ifeq ($(1),32)
+	$(Q) echo '#include "asm/syscall32.h"'						>> $$@
+endif
+	$(Q) cat $$< | awk '/^__NR/{print "extern long", $(AV)3,			\
+			substr($(AV)0, index($(AV)0,$(AV)4)), ";"}'			>> $$@
+	$(Q) echo "#endif /* ASM_SYSCALL_PROTO_H_$(1)__ */"				>> $$@
+endef
+
+define gen-rule-sys-asm
+$(sys-asm): $(sys-def) $(sys-asm-common) $(sys-codes) $(sys-proto)
+	$(call msg-gen, $$@)
+	$(Q) echo "/* Autogenerated, don't edit */"					>  $$@
+	$(Q) echo '#include "std/syscall-codes-$(1).h"'					>> $$@
+	$(Q) echo '#include "$(sys-asm-common-name)"'					>> $$@
+	$(Q) cat $$< | awk '/^__NR/{print "SYSCALL(", $(AV)3, ",", $(AV)2, ")"}'	>> $$@
+endef
+
+define gen-rule-sys-exec-tbl
+$(sys-exec-tbl): $(sys-def) $(sys-codes) $(sys-proto) $(sys-proto-generic)
+	$(call msg-gen, $$@)
+	$(Q) echo "/* Autogenerated, don't edit */"					>  $$@
+	$(Q) cat $$< | awk '/^__NR/{print						\
+		"SYSCALL(", substr($(AV)3, 5), ",", $(AV)2, ")"}'			>> $$@
+endef
+
+$(sys-codes-generic): $(ARCH_DIR)/std/syscalls/syscall_32.tbl
+	$(call msg-gen, $@)
+	$(Q) echo "/* Autogenerated, don't edit */"			>  $@
+	$(Q) echo "#ifndef __ASM_CR_SYSCALL_CODES_H__"			>> $@
+	$(Q) echo "#define __ASM_CR_SYSCALL_CODES_H__"			>> $@
+	$(Q) echo '#include "std/syscall-codes-64.h"'			>> $@
+	$(Q) cat $< | awk '/^__NR/{NR32=$$1;				\
+		sub("^__NR", "__NR32", NR32);				\
+		print "\n#ifndef ", NR32;				\
+		print "#define ", NR32, $$2;				\
+		print "#endif";}'					>> $@
+	$(Q) echo "#endif /* __ASM_CR_SYSCALL_CODES_H__ */"		>> $@
+
+$(sys-proto-generic): $(strip $(call map,sys-proto,$(sys-bits)))
+	$(call msg-gen, $@)
+	$(Q) echo "/* Autogenerated, don't edit */"			>  $@
+	$(Q) echo "#ifndef __ASM_CR_SYSCALL_PROTO_H__"			>> $@
+	$(Q) echo "#define __ASM_CR_SYSCALL_PROTO_H__"			>> $@
+	$(Q) echo ""							>> $@
+	$(Q) echo "#ifdef CONFIG_X86_32"				>> $@
+	$(Q) echo '#include "std/syscall-32.h"'				>> $@
+	$(Q) echo "#else"						>> $@
+	$(Q) echo '#include "std/syscall-64.h"'				>> $@
+	$(Q) echo "#endif /* CONFIG_X86_32 */"				>> $@
+	$(Q) echo ""							>> $@
+	$(Q) echo "#endif /* __ASM_CR_SYSCALL_PROTO_H__ */"		>> $@
+
+$(eval $(call map,gen-rule-sys-codes,$(sys-bits)))
+$(eval $(call map,gen-rule-sys-proto,$(sys-bits)))
+$(eval $(call map,gen-rule-sys-asm,$(sys-bits)))
+
+std-headers-deps	+= $(call sys-codes,$(sys-bits))
+std-headers-deps	+= $(call sys-proto,$(sys-bits))
+std-headers-deps	+= $(call sys-asm,$(sys-bits))
+std-headers-deps	+= $(sys-codes-generic)
+std-headers-deps	+= $(sys-proto-generic)
+
+$(addprefix $(obj)/,$(std-obj-y:%.o=%.d)): | $(std-headers-deps)
+$(addprefix $(obj)/,$(std-obj-y:%.o=%.i)): | $(std-headers-deps)
+$(addprefix $(obj)/,$(std-obj-y:%.o=%.s)): | $(std-headers-deps)
+$(addprefix $(obj)/,$(std-obj-y)): | $(std-headers-deps)
diff --git a/compel/plugins/include/uapi/plugin-std.h b/compel/plugins/include/uapi/plugin-std.h
new file mode 100644
index 000000000000..292db8839383
--- /dev/null
+++ b/compel/plugins/include/uapi/plugin-std.h
@@ -0,0 +1,6 @@
+#ifndef COMPEL_PLUGIN_STD_STD_H__
+#define COMPEL_PLUGIN_STD_STD_H__
+
+#include "uapi/std/syscall.h"
+
+#endif /* COMPEL_PLUGIN_STD_STD_H__ */
diff --git a/compel/plugins/include/uapi/std/string.h b/compel/plugins/include/uapi/std/string.h
new file mode 100644
index 000000000000..8aec886bd093
--- /dev/null
+++ b/compel/plugins/include/uapi/std/string.h
@@ -0,0 +1,28 @@
+#ifndef COMPEL_PLUGIN_STD_STRING_H__
+#define COMPEL_PLUGIN_STD_STRING_H__
+
+#include <sys/types.h>
+#include <stdbool.h>
+#include <stdarg.h>
+
+/* Standard file descriptors.  */
+#define	STDIN_FILENO	0	/* Standard input.  */
+#define	STDOUT_FILENO	1	/* Standard output.  */
+#define	STDERR_FILENO	2	/* Standard error output.  */
+
+
+extern void __std_putc(int fd, char c);
+extern void __std_puts(int fd, const char *s);
+extern void __std_printk(int fd, const char *format, va_list args);
+extern void __std_printf(int fd, const char *format, ...);
+
+#define std_printf(fmt, ...)	__std_printf(STDOUT_FILENO, fmt, ##__VA_ARGS__)
+#define std_puts(s)		__std_puts(STDOUT_FILENO, s)
+#define std_putchar(c)		__std_putc(STDOUT_FILENO, c)
+
+extern unsigned long std_strtoul(const char *nptr, char **endptr, int base);
+extern void *std_memcpy(void *to, const void *from, unsigned int n);
+extern int std_memcmp(const void *cs, const void *ct, size_t count);
+extern int std_strcmp(const char *cs, const char *ct);
+
+#endif /* COMPEL_PLUGIN_STD_STRING_H__ */
diff --git a/compel/plugins/include/uapi/std/syscall-types.h b/compel/plugins/include/uapi/std/syscall-types.h
new file mode 100644
index 000000000000..1b8188299103
--- /dev/null
+++ b/compel/plugins/include/uapi/std/syscall-types.h
@@ -0,0 +1,55 @@
+/*
+ * Please add here type definitions if
+ * syscall prototypes need them.
+ */
+
+#ifndef COMPEL_SYSCALL_TYPES_H__
+#define COMPEL_SYSCALL_TYPES_H__
+
+#include <arpa/inet.h>
+#include <sys/time.h>
+#include <stdbool.h>
+#include <signal.h>
+#include <sched.h>
+#include <fcntl.h>
+#include <time.h>
+
+struct cap_header {
+	u32 version;
+	int pid;
+};
+
+struct cap_data {
+	u32 eff;
+	u32 prm;
+	u32 inh;
+};
+
+struct robust_list_head;
+struct file_handle;
+struct itimerspec;
+struct io_event;
+struct sockaddr;
+struct timespec;
+struct siginfo;
+struct msghdr;
+struct rusage;
+struct iocb;
+
+typedef unsigned long aio_context_t;
+
+#ifndef F_GETFD
+# define F_GETFD 1
+#endif
+
+struct krlimit {
+	unsigned long rlim_cur;
+	unsigned long rlim_max;
+};
+
+/* Type of timers in the kernel.  */
+typedef int kernel_timer_t;
+
+#include "asm/std/syscall-types.h"
+
+#endif /* COMPEL_SYSCALL_TYPES_H__ */
diff --git a/compel/plugins/std/std.c b/compel/plugins/std/std.c
new file mode 100644
index 000000000000..b3ea971f9079
--- /dev/null
+++ b/compel/plugins/std/std.c
@@ -0,0 +1,89 @@
+#include <sys/types.h>
+
+#include "uapi/int.h"
+#include "uapi/plugins.h"
+#include "uapi/plugin-std.h"
+
+extern int main(void *arg_p, unsigned int arg_s);
+
+static struct prologue_init_args *init_args;
+static int ctl_socket = -1;
+
+int std_ctl_sock(void)
+{
+	return ctl_socket;
+}
+
+static int init_socket(struct prologue_init_args *args)
+{
+	int ret;
+
+	ctl_socket = sys_socket(PF_UNIX, SOCK_SEQPACKET, 0);
+	if (ctl_socket < 0)
+		return ctl_socket;
+
+	ret = sys_connect(ctl_socket, (struct sockaddr *)&args->ctl_sock_addr, args->ctl_sock_addr_len);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int fini_socket(void)
+{
+	char buf[32];
+	int ret = 0;
+
+	ret = sys_shutdown(ctl_socket, SHUT_WR);
+	if (ret)
+		goto err;
+
+	ret = sys_recvfrom(ctl_socket, buf, sizeof(buf), MSG_WAITALL, 0, 0);
+	if (ret)
+		goto err;
+err:
+	sys_close(ctl_socket);
+	ctl_socket = -1;
+	return ret;
+}
+
+#define plugin_init_count(size)	((size) / (sizeof(plugin_init_t *)))
+
+int __export_std_compel_start(struct prologue_init_args *args,
+			      const plugin_init_t * const *init_array,
+			      size_t init_size)
+{
+	unsigned int i;
+	int ret = 0;
+
+	init_args = args;
+
+	ret = init_socket(args);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < plugin_init_count(init_size); i++) {
+		const plugin_init_t *d = init_array[i];
+
+		if (d && d->init) {
+			ret = d->init();
+			if (ret)
+				break;
+		}
+	}
+
+	if (!ret)
+		ret = main(args->arg_p, args->arg_s);
+
+	for (; i > 0; i--) {
+		const plugin_init_t *d = init_array[i - 1];
+
+		if (d && d->exit)
+			d->exit();
+	}
+
+	fini_socket();
+	return ret;
+}
+
+PLUGIN_REGISTER_DUMMY(std)
diff --git a/compel/plugins/std/string.c b/compel/plugins/std/string.c
new file mode 100644
index 000000000000..f4181f92a903
--- /dev/null
+++ b/compel/plugins/std/string.c
@@ -0,0 +1,262 @@
+#include <sys/types.h>
+#include <stdbool.h>
+#include <stdarg.h>
+
+#include "uapi/std/syscall.h"
+#include "uapi/std/string.h"
+
+static const char conv_tab[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+
+void __std_putc(int fd, char c)
+{
+	sys_write(fd, &c, 1);
+}
+
+void __std_puts(int fd, const char *s)
+{
+	for (; *s; s++)
+		__std_putc(fd, *s);
+}
+
+static size_t __std_vprint_long_hex(char *buf, size_t blen, unsigned long num, char **ps)
+{
+	char *s = &buf[blen - 2];
+
+	buf[blen - 1] = '\0';
+
+	if (num == 0) {
+		*s = '0', s--;
+		goto done;
+	}
+
+	while (num > 0) {
+		*s = conv_tab[num % 16], s--;
+		num /= 16;
+	}
+
+done:
+	s++;
+	*ps = s;
+	return blen - (s - buf);
+}
+
+static size_t __std_vprint_long(char *buf, size_t blen, long num, char **ps)
+{
+	char *s = &buf[blen - 2];
+	int neg = 0;
+
+	buf[blen - 1] = '\0';
+
+	if (num < 0) {
+		neg = 1;
+		num = -num;
+	} else if (num == 0) {
+		*s = '0';
+		s--;
+		goto done;
+	}
+
+	while (num > 0) {
+		*s = (num % 10) + '0';
+		s--;
+		num /= 10;
+	}
+
+	if (neg) {
+		*s = '-';
+		s--;
+	}
+done:
+	s++;
+	*ps = s;
+	return blen - (s - buf);
+}
+
+void __std_printk(int fd, const char *format, va_list args)
+{
+	const char *s = format;
+
+	for (; *s != '\0'; s++) {
+		char buf[32], *t;
+		int along = 0;
+
+		if (*s != '%') {
+			__std_putc(fd, *s);
+			continue;
+		}
+
+		s++;
+		if (*s == 'l') {
+			along = 1;
+			s++;
+			if (*s == 'l')
+				s++;
+		}
+
+		switch (*s) {
+		case 's':
+			__std_puts(fd, va_arg(args, char *));
+			break;
+		case 'd':
+			__std_vprint_long(buf, sizeof(buf),
+					  along ?
+					  va_arg(args, long) :
+					  (long)va_arg(args, int),
+					  &t);
+			__std_puts(fd, t);
+			break;
+		case 'x':
+			__std_vprint_long_hex(buf, sizeof(buf),
+					      along ?
+					      va_arg(args, long) :
+					      (long)va_arg(args, int),
+					      &t);
+			__std_puts(fd, t);
+			break;
+		}
+	}
+}
+
+void __std_printf(int fd, const char *format, ...)
+{
+	va_list args;
+
+	va_start(args, format);
+	__std_printk(fd, format, args);
+	va_end(args);
+}
+
+static inline bool __isspace(unsigned char c)
+{
+	return	c == ' '  || c == '\f' ||
+		c == '\n' || c == '\r' ||
+		c == '\t' || c == '\v';
+}
+
+static unsigned char __tolower(unsigned char c)
+{
+	return (c <= 'Z' && c >= 'A') ? c - 'A' + 'a' : c;
+}
+
+static inline bool __isalpha(unsigned char c)
+{
+	return ((c <= 'Z' && c >= 'A') ||
+		(c <= 'z' && c >= 'a'));
+}
+
+static inline bool __isdigit(unsigned char c)
+{
+	return (c <= '9' && c >= '0');
+}
+
+static inline bool __isalnum(unsigned char c)
+{
+	return (__isalpha(c) || __isdigit(c));
+}
+
+static unsigned int __conv_val(unsigned char c)
+{
+	if (__isdigit(c))
+		return c - '0';
+	else if (__isalpha(c))
+		return &conv_tab[__tolower(c)] - conv_tab;
+	return -1u;
+}
+
+unsigned long std_strtoul(const char *nptr, char **endptr, int base)
+{
+	const char *s = nptr;
+	bool neg = false;
+	unsigned int v;
+	long num = 0;
+
+	if (base < 0 || base == 1 || base > 36)
+		goto fin;
+
+	while (__isspace(*s))
+		s++;
+	if (!*s)
+		goto fin;
+
+	if (*s == '-')
+		neg = true, s++;
+
+	if (base == 0) {
+		if (s[0] == '0') {
+			unsigned char p = __tolower(s[1]);
+			switch (p) {
+			case 'b':
+				base = 2, s += 2;
+				break;
+			case 'x':
+				base = 16, s += 2;
+				break;
+			default:
+				base = 8, s += 1;
+				break;
+			}
+		} else
+			base = 10;
+	} else if (base == 16) {
+		if (s[0] == '0' && __tolower(s[1]) == 'x')
+			s += 2;
+	}
+
+	for (; *s; s++) {
+		if (__isspace(*s))
+			continue;
+		if (!__isalnum(*s))
+		    goto fin;
+		v = __conv_val(*s);
+		if (v == -1u || v > base)
+			goto fin;
+		num *= base;
+		num += v;
+	}
+
+fin:
+	if (endptr)
+		*endptr = (char *)s;
+	return neg ? (unsigned long)-num : (unsigned long)num;
+}
+
+void *std_memcpy(void *to, const void *from, unsigned int 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");
+	return to;
+}
+
+int std_memcmp(const void *cs, const void *ct, size_t count)
+{
+	const unsigned char *su1, *su2;
+	int res = 0;
+
+	for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
+		if ((res = *su1 - *su2) != 0)
+			break;
+	return res;
+}
+
+int std_strcmp(const char *cs, const char *ct)
+{
+	unsigned char c1, c2;
+
+	while (1) {
+		c1 = *cs++;
+		c2 = *ct++;
+		if (c1 != c2)
+			return c1 < c2 ? -1 : 1;
+		if (!c1)
+			break;
+	}
+	return 0;
+}
-- 
2.7.4



More information about the CRIU mailing list