[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