[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