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

Pavel Emelyanov xemul at virtuozzo.com
Thu Sep 1 02:31:26 PDT 2016


This is also to be splitted. First patch -- plugins engine into compel
with good comment about what it is and how to use one. Second patch --
the std plugin itself.

-- Pavel

On 08/31/2016 04:48 PM, Cyrill Gorcunov wrote:
> 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;
> +}
> 



More information about the CRIU mailing list