#define __UK_NAME2SCALLE_FN(name) UK_CONCAT(uk_syscall_e_, name)
#define __UK_NAME2SCALLR_FN(name) UK_CONCAT(uk_syscall_r_, name)
+#define __UK_NAME2SCALLDO_FN(name) UK_CONCAT(uk_syscall_do_, name)
#define UK_ARG_MAP0(...)
#define UK_ARG_MAP2(m, type, arg) m(type, arg)
* UK_LLSYSCALL_DEFINE()
* Low-level variant, does not provide a libc-style wrapper
*/
-#define __UK_LLSYSCALL_DEFINE(x, rtype, name, ename, rname, ...) \
+#define __UK_LLSYSCALL_DEFINE(x, rtype, name, ename, rname, doname, ...)\
long ename(UK_ARG_MAPx(x, UK_S_ARG_LONG, __VA_ARGS__)); \
long rname(UK_ARG_MAPx(x, UK_S_ARG_LONG, __VA_ARGS__)) \
{ \
_uk_syscall_wrapper_do_exittab(NULL); \
\
return ret; \
+ } \
+ \
+ long doname(UK_ARG_MAPx(x, UK_S_ARG_LONG, __VA_ARGS__)) \
+ { \
+ int _errno = errno; \
+ long ret; \
+ \
+ __UK_SYSCALL_PRINTD(x, rtype, doname, __VA_ARGS__); \
+ \
+ errno = 0; \
+ ret = (long) __##ename( \
+ UK_ARG_MAPx(x, UK_S_ARG_CAST_ACTUAL, __VA_ARGS__)); \
+ if (ret == -1) \
+ ret = errno ? -errno : -EFAULT; \
+ errno = _errno; \
+ \
+ return ret; \
} \
static inline rtype __##ename(UK_ARG_MAPx(x, \
UK_S_ARG_ACTUAL_MAYBE_UNUSED,\
name, \
__UK_NAME2SCALLE_FN(name), \
__UK_NAME2SCALLR_FN(name), \
+ __UK_NAME2SCALLDO_FN(name), \
__VA_ARGS__)
/*
* in case UK_LIBC_SYSCALLS is enabled
*/
#if UK_LIBC_SYSCALLS
-#define __UK_SYSCALL_DEFINE(x, rtype, name, ename, rname, ...) \
+#define __UK_SYSCALL_DEFINE(x, rtype, name, ename, rname, doname, ...) \
long ename(UK_ARG_MAPx(x, UK_S_ARG_LONG, __VA_ARGS__)); \
rtype name(UK_ARG_MAPx(x, UK_S_ARG_ACTUAL, __VA_ARGS__)) \
{ \
UK_ARG_MAPx(x, UK_S_ARG_CAST_LONG, __VA_ARGS__)); \
return ret; \
} \
- __UK_LLSYSCALL_DEFINE(x, rtype, name, ename, rname, __VA_ARGS__)
+ __UK_LLSYSCALL_DEFINE(x, rtype, name, ename, rname, doname, __VA_ARGS__)
#define _UK_SYSCALL_DEFINE(...) __UK_SYSCALL_DEFINE(__VA_ARGS__)
#define UK_SYSCALL_DEFINE(rtype, name, ...) \
_UK_SYSCALL_DEFINE(UK_NARGS(__VA_ARGS__), \
name, \
__UK_NAME2SCALLE_FN(name), \
__UK_NAME2SCALLR_FN(name), \
+ __UK_NAME2SCALLDO_FN(name), \
__VA_ARGS__)
#else
#define UK_SYSCALL_DEFINE(rtype, name, ...) \
name, \
__UK_NAME2SCALLE_FN(name), \
__UK_NAME2SCALLR_FN(name), \
+ __UK_NAME2SCALLDO_FN(name), \
__VA_ARGS__)
#endif /* UK_LIBC_SYSCALLS */
* UK_LLSYSCALL_R_DEFINE()
* Low-level variant, does not provide a libc-style wrapper
*/
-#define __UK_LLSYSCALL_R_DEFINE(x, rtype, name, ename, rname, ...) \
+#define __UK_LLSYSCALL_R_DEFINE(x, rtype, name, ename, rname, doname, ...)\
long rname(UK_ARG_MAPx(x, UK_S_ARG_LONG, __VA_ARGS__)); \
long ename(UK_ARG_MAPx(x, UK_S_ARG_LONG, __VA_ARGS__)) \
{ \
_uk_syscall_wrapper_do_exittab(NULL); \
\
return ret; \
+ } \
+ \
+ long doname(UK_ARG_MAPx(x, UK_S_ARG_LONG, __VA_ARGS__)) \
+ { \
+ long ret; \
+ \
+ __UK_SYSCALL_PRINTD(x, rtype, doname, __VA_ARGS__); \
+ \
+ ret = (long) __##rname( \
+ UK_ARG_MAPx(x, UK_S_ARG_CAST_ACTUAL, __VA_ARGS__)); \
+ return ret; \
} \
static inline rtype __##rname(UK_ARG_MAPx(x, \
UK_S_ARG_ACTUAL_MAYBE_UNUSED,\
name, \
__UK_NAME2SCALLE_FN(name), \
__UK_NAME2SCALLR_FN(name), \
+ __UK_NAME2SCALLDO_FN(name), \
__VA_ARGS__)
-#define __UK_LLSYSCALL_R_E_DEFINE(x, rtype, name, ename, rname, ...) \
+#define __UK_LLSYSCALL_R_E_DEFINE(x, rtype, name, ename, rname, doname, ...)\
long rname(long _execenv); \
long __used ename(long _execenv) \
{ \
_uk_syscall_wrapper_do_exittab(execenv); \
\
return ret; \
+ } \
+ \
+ long __used doname(long _execenv) \
+ { \
+ struct ukarch_execenv *execenv; \
+ long ret; \
+ \
+ execenv = (struct ukarch_execenv *)_execenv; \
+ __UK_SYSCALL_EXECENV_PRINTD(execenv, x, rtype, doname, \
+ __VA_ARGS__); \
+ \
+ ret = (long) __##rname(UK_EXECENV_CALLMAPx(x, \
+ UK_S_ARG_ACTUAL, \
+ __VA_ARGS__)); \
+ \
+ return ret; \
} \
static inline rtype __used __##rname(UK_EXECENV_DECLMAPx( \
UK_S_EXECENV_ARG_ACTUAL_MAYBE_UNUSED,\
__UK_NAME2SCALLR_FN(e_##name), \
UK_NARGS(__VA_ARGS__), \
__VA_ARGS__) \
+ UK_SYSCALL_EXECENV_PROLOGUE_DEFINE(__UK_NAME2SCALLDO_FN(name), \
+ __UK_NAME2SCALLDO_FN(e_##name), \
+ UK_NARGS(__VA_ARGS__), \
+ __VA_ARGS__) \
_UK_LLSYSCALL_R_E_DEFINE(UK_NARGS(__VA_ARGS__), \
rtype, \
name, \
__UK_NAME2SCALLE_FN(e_##name), \
__UK_NAME2SCALLR_FN(e_##name), \
+ __UK_NAME2SCALLDO_FN(e_##name), \
__VA_ARGS__)
/*
* in case UK_LIBC_SYSCALLS is enabled
*/
#if UK_LIBC_SYSCALLS
-#define __UK_SYSCALL_R_DEFINE(x, rtype, name, ename, rname, ...) \
+#define __UK_SYSCALL_R_DEFINE(x, rtype, name, ename, rname, doname, ...)\
long ename(UK_ARG_MAPx(x, UK_S_ARG_LONG, __VA_ARGS__)); \
rtype name(UK_ARG_MAPx(x, UK_S_ARG_ACTUAL, __VA_ARGS__)) \
{ \
UK_ARG_MAPx(x, UK_S_ARG_CAST_LONG, __VA_ARGS__)); \
return ret; \
} \
- __UK_LLSYSCALL_R_DEFINE(x, rtype, name, ename, rname, __VA_ARGS__)
+ __UK_LLSYSCALL_R_DEFINE(x, rtype, name, ename, rname, doname, \
+ __VA_ARGS__)
#define _UK_SYSCALL_R_DEFINE(...) __UK_SYSCALL_R_DEFINE(__VA_ARGS__)
#define UK_SYSCALL_R_DEFINE(rtype, name, ...) \
_UK_SYSCALL_R_DEFINE(UK_NARGS(__VA_ARGS__), \
name, \
__UK_NAME2SCALLE_FN(name), \
__UK_NAME2SCALLR_FN(name), \
+ __UK_NAME2SCALLDO_FN(name), \
__VA_ARGS__)
#else
#define UK_SYSCALL_R_DEFINE(rtype, name, ...) \
name, \
__UK_NAME2SCALLE_FN(name), \
__UK_NAME2SCALLR_FN(name), \
+ __UK_NAME2SCALLDO_FN(name), \
__VA_ARGS__)
#endif /* UK_LIBC_SYSCALLS */
long __UK_NAME2SCALLE_FN(syscall_name)(__UK_SPROTO_ARGSx(args_nr))
#define UK_SYSCALL_R_PROTO(args_nr, syscall_name) \
long __UK_NAME2SCALLR_FN(syscall_name)(__UK_SPROTO_ARGSx(args_nr))
+#define UK_SYSCALL_DO_PROTO(args_nr, syscall_name) \
+ long __UK_NAME2SCALLDO_FN(syscall_name)(__UK_SPROTO_ARGSx(args_nr))
#define uk_syscall_e_stub(syscall_name) ({ \
uk_pr_debug("System call \"" syscall_name \
long uk_syscall_r(long nr, ...);
long uk_vsyscall_r(long nr, va_list arg);
long uk_syscall6_r_e(struct ukarch_execenv *execenv);
+long uk_syscall6_do_e(struct ukarch_execenv *execenv);
long uk_syscall6_r(long nr, long arg1, long arg2, long arg3,
long arg4, long arg5, long arg6);
--- /dev/null
+BEGIN {
+ max_args = 6
+ print "/* Auto generated file. DO NOT EDIT */\n\n"
+
+ print "#include <uk/print.h>"
+ print "#include <uk/syscall.h>"
+ print "#include <uk/bits/syscall_linuxabi.h>\n"
+
+ print "UK_SYSCALL_EXECENV_PROLOGUE_DEFINE(uk_syscall6_do, uk_syscall6_do_e,"
+ print "\t\t\t\t14, long, nr, long, arg1, long, arg2, long, arg3, long, arg4, long, arg5, long, arg6)";
+ print "\nlong __used uk_syscall6_do_e(struct ukarch_execenv *execenv)"
+ print "{"
+ print "\tlong ret;"
+ print "\n\tswitch (execenv->regs.__syscall_rsyscall) {"
+}
+
+/[a-zA-Z0-9]+-[0-9]+/{
+ name = $1
+ sys_name = "SYS_" name
+ uk_syscall_do = "uk_syscall_do_" name
+ uk_syscall_do_e = "uk_syscall_do_e_" name
+ args_nr = $2 + 0
+ printf "\n#ifdef HAVE_uk_syscall_%s\n", name;
+ printf "\tcase %s:\n", sys_name;
+ printf "\n#ifdef HAVE_uk_syscall_e_%s\n", name;
+ printf "\t\tret = %s((long)execenv);\n", uk_syscall_do_e;
+ printf "#else /* !HAVE_uk_syscall_e_%s */\n", name;
+ printf "\t\tret = %s(\n\t\t\t\t\t", uk_syscall_do;
+ for (i = 0; i < args_nr - 1; i++)
+ printf("execenv->regs.__syscall_rarg%d, ", i)
+ if (args_nr > 0)
+ printf("execenv->regs.__syscall_rarg%d", args_nr - 1)
+ printf(");\n")
+ printf "\n#endif /* !HAVE_uk_syscall_e_%s */\n\n", name;
+ printf "\t\tbreak;\n"
+ printf "\n#endif /* HAVE_uk_syscall_%s */\n", name;
+}
+
+END {
+ printf "\tdefault:\n"
+ printf "\t\tuk_pr_debug(\"syscall \\\"%%s\\\" is not available\\n\", uk_syscall_name(execenv->regs.__syscall_rsyscall));\n"
+ printf "\t\tret = -ENOSYS;\n"
+ printf "\t}\n"
+ printf "\treturn ret;\n"
+ printf "}\n"
+ printf "\n"
+}