linux-user pull request 2020-07-02
Update linux-user maintainer Improve strace output for some syscalls Display contents of ioctl() parameters Fix sparc64 flushw operation -----BEGIN PGP SIGNATURE----- iQJGBAABCAAwFiEEzS913cjjpNwuT1Fz8ww4vT8vvjwFAl8ArXESHGxhdXJlbnRA dml2aWVyLmV1AAoJEPMMOL0/L748ETEP/iUDv43DOpCBkDGQCps32ZpfBh4RaIiI IonBYyductpB/N5UGNVc461IlJuby6NTv6r5eoFfbVkHOly0Ko8SEHJ1eio3krmR ViEr3IVF67zSNqBHDPOKPZ2c7aC0AWJ8jQshCtgdgKbFmJM5630T0HeKk7ufdFsM POXI08Lv8CkTHd1PpnCxGx+s7XcvPV1ZSSseDPOY3cvYMB44NHDKOdlF2ggniiCw 1QeCUhOMSONxjtZUimI+/5qDmD21R6e0tKq5CuTnpnN8vPWCfqO3qyJNasY3EqNm vA2v9RFeEqScXXMovCiJlsxtDNAzbWI+TXariQA4EFUBZ+FhhZM12HyVxudnQf7a k2VRlOakYkidAJiqb+ZAWDGB7xEybvblmkxkT/CF2gPTMZW5SM0VnxZmWH+BulWH BNtEhlUT4rDxCwL+4Xw2SIL+2veGs4CduomyVHBjXhDHlHlgyxWasYz9s1DojVIP jzr+Foi0H6BQDKFiwhYqInPw7QRMjjNTXVc/K3ytmCOSO9Vu0pT7MDKiIBYA7cVh SzNsLR0UdTLv3SY9Gno4LCU5SnAJDDnCErxXckdoqmNqxyJ2NAKQRKoV6pddOxB5 EwsITUx92g3pORdMOqLFK1Xx1oxGr4GlRnJX1qBOGZPxYKSy3anuoewy08Q8NT9M v+zksJc4wLd4 =JdG0 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-5.1-pull-request' into staging linux-user pull request 2020-07-02 Update linux-user maintainer Improve strace output for some syscalls Display contents of ioctl() parameters Fix sparc64 flushw operation # gpg: Signature made Sat 04 Jul 2020 17:25:21 BST # gpg: using RSA key CD2F75DDC8E3A4DC2E4F5173F30C38BD3F2FBE3C # gpg: issuer "laurent@vivier.eu" # gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [full] # gpg: aka "Laurent Vivier <laurent@vivier.eu>" [full] # gpg: aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [full] # Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F 5173 F30C 38BD 3F2F BE3C * remotes/vivier2/tags/linux-user-for-5.1-pull-request: MAINTAINERS: update linux-user maintainer linux-user: Add strace support for printing arguments of ioctl() linux-user: Add thunk argument types for SIOCGSTAMP and SIOCGSTAMPNS linux-user: Add strace support for printing arguments of fallocate() linux-user: Add strace support for printing arguments of chown()/lchown() linux-user: Add strace support for printing arguments of lseek() linux-user: Add strace support for printing argument of syscalls used for extended attributes linux-user: Add strace support for a group of syscalls linux-user: Extend strace support to enable argument printing after syscall execution linux-user: syscall: ioctls: support DRM_IOCTL_VERSION linux-user/sparc64: Fix the handling of window spill trap target/sparc: Translate flushw opcode Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
7623b5ba01
@ -2630,8 +2630,7 @@ F: bsd-user/
|
||||
F: default-configs/*-bsd-user.mak
|
||||
|
||||
Linux user
|
||||
M: Riku Voipio <riku.voipio@iki.fi>
|
||||
R: Laurent Vivier <laurent@vivier.eu>
|
||||
M: Laurent Vivier <laurent@vivier.eu>
|
||||
S: Maintained
|
||||
F: linux-user/
|
||||
F: default-configs/*-linux-user.mak
|
||||
|
@ -413,7 +413,11 @@ static void save_window(CPUSPARCState *env)
|
||||
save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
|
||||
env->wim = new_wim;
|
||||
#else
|
||||
save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
|
||||
/*
|
||||
* cansave is zero if the spill trap handler is triggered by `save` and
|
||||
* nonzero if triggered by a `flushw`
|
||||
*/
|
||||
save_window_offset(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
|
||||
env->cansave++;
|
||||
env->canrestore--;
|
||||
#endif
|
||||
|
10
configure
vendored
10
configure
vendored
@ -3194,6 +3194,13 @@ if ! check_include "ifaddrs.h" ; then
|
||||
have_ifaddrs_h=no
|
||||
fi
|
||||
|
||||
#########################################
|
||||
# libdrm check
|
||||
have_drm_h=no
|
||||
if check_include "libdrm/drm.h" ; then
|
||||
have_drm_h=yes
|
||||
fi
|
||||
|
||||
##########################################
|
||||
# VTE probe
|
||||
|
||||
@ -7377,6 +7384,9 @@ fi
|
||||
if test "$have_ifaddrs_h" = "yes" ; then
|
||||
echo "HAVE_IFADDRS_H=y" >> $config_host_mak
|
||||
fi
|
||||
if test "$have_drm_h" = "yes" ; then
|
||||
echo "HAVE_DRM_H=y" >> $config_host_mak
|
||||
fi
|
||||
if test "$have_broken_size_max" = "yes" ; then
|
||||
echo "HAVE_BROKEN_SIZE_MAX=y" >> $config_host_mak
|
||||
fi
|
||||
|
@ -73,6 +73,7 @@ void thunk_register_struct_direct(int id, const char *name,
|
||||
const StructEntry *se1);
|
||||
const argtype *thunk_convert(void *dst, const void *src,
|
||||
const argtype *type_ptr, int to_host);
|
||||
const argtype *thunk_print(void *arg, const argtype *type_ptr);
|
||||
|
||||
extern StructEntry *struct_entries;
|
||||
|
||||
|
@ -279,13 +279,17 @@
|
||||
* FIXME: create a macro to define this kind of entry
|
||||
*/
|
||||
{ TARGET_SIOCGSTAMP_OLD, TARGET_SIOCGSTAMP_OLD,
|
||||
"SIOCGSTAMP_OLD", IOC_R, do_ioctl_SIOCGSTAMP },
|
||||
"SIOCGSTAMP_OLD", IOC_R, do_ioctl_SIOCGSTAMP,
|
||||
{ MK_PTR(MK_STRUCT(STRUCT_timeval)) } },
|
||||
{ TARGET_SIOCGSTAMPNS_OLD, TARGET_SIOCGSTAMPNS_OLD,
|
||||
"SIOCGSTAMPNS_OLD", IOC_R, do_ioctl_SIOCGSTAMPNS },
|
||||
"SIOCGSTAMPNS_OLD", IOC_R, do_ioctl_SIOCGSTAMPNS,
|
||||
{ MK_PTR(MK_STRUCT(STRUCT_timespec)) } },
|
||||
{ TARGET_SIOCGSTAMP_NEW, TARGET_SIOCGSTAMP_NEW,
|
||||
"SIOCGSTAMP_NEW", IOC_R, do_ioctl_SIOCGSTAMP },
|
||||
"SIOCGSTAMP_NEW", IOC_R, do_ioctl_SIOCGSTAMP,
|
||||
{ MK_PTR(MK_STRUCT(STRUCT__kernel_sock_timeval)) } },
|
||||
{ TARGET_SIOCGSTAMPNS_NEW, TARGET_SIOCGSTAMPNS_NEW,
|
||||
"SIOCGSTAMPNS_NEW", IOC_R, do_ioctl_SIOCGSTAMPNS },
|
||||
"SIOCGSTAMPNS_NEW", IOC_R, do_ioctl_SIOCGSTAMPNS,
|
||||
{ MK_PTR(MK_STRUCT(STRUCT__kernel_timespec)) } },
|
||||
|
||||
IOCTL(RNDGETENTCNT, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(RNDADDTOENTCNT, IOC_W, MK_PTR(TYPE_INT))
|
||||
@ -574,6 +578,11 @@
|
||||
IOCTL_SPECIAL(SIOCDELRT, IOC_W, do_ioctl_rt,
|
||||
MK_PTR(MK_STRUCT(STRUCT_rtentry)))
|
||||
|
||||
#ifdef HAVE_DRM_H
|
||||
IOCTL_SPECIAL(DRM_IOCTL_VERSION, IOC_RW, do_ioctl_drm,
|
||||
MK_PTR(MK_STRUCT(STRUCT_drm_version)))
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_TIOCSTART
|
||||
IOCTL_IGNORE(TIOCSTART)
|
||||
IOCTL_IGNORE(TIOCSTOP)
|
||||
|
@ -184,6 +184,26 @@ struct linux_binprm {
|
||||
int (*core_dump)(int, const CPUArchState *); /* coredump routine */
|
||||
};
|
||||
|
||||
typedef struct IOCTLEntry IOCTLEntry;
|
||||
|
||||
typedef abi_long do_ioctl_fn(const IOCTLEntry *ie, uint8_t *buf_temp,
|
||||
int fd, int cmd, abi_long arg);
|
||||
|
||||
struct IOCTLEntry {
|
||||
int target_cmd;
|
||||
unsigned int host_cmd;
|
||||
const char *name;
|
||||
int access;
|
||||
do_ioctl_fn *do_ioctl;
|
||||
const argtype arg_type[5];
|
||||
};
|
||||
|
||||
extern IOCTLEntry ioctl_entries[];
|
||||
|
||||
#define IOC_R 0x0001
|
||||
#define IOC_W 0x0002
|
||||
#define IOC_RW (IOC_R | IOC_W)
|
||||
|
||||
void do_init_thread(struct target_pt_regs *regs, struct image_info *infop);
|
||||
abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
|
||||
abi_ulong stringp, int push_ptr);
|
||||
@ -383,7 +403,9 @@ int host_to_target_waitstatus(int status);
|
||||
void print_syscall(int num,
|
||||
abi_long arg1, abi_long arg2, abi_long arg3,
|
||||
abi_long arg4, abi_long arg5, abi_long arg6);
|
||||
void print_syscall_ret(int num, abi_long arg1);
|
||||
void print_syscall_ret(int num, abi_long ret,
|
||||
abi_long arg1, abi_long arg2, abi_long arg3,
|
||||
abi_long arg4, abi_long arg5, abi_long arg6);
|
||||
/**
|
||||
* print_taken_signal:
|
||||
* @target_signum: target signal being taken
|
||||
@ -668,6 +690,22 @@ static inline int is_error(abi_long ret)
|
||||
return (abi_ulong)ret >= (abi_ulong)(-4096);
|
||||
}
|
||||
|
||||
#if TARGET_ABI_BITS == 32
|
||||
static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
|
||||
{
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
return ((uint64_t)word0 << 32) | word1;
|
||||
#else
|
||||
return ((uint64_t)word1 << 32) | word0;
|
||||
#endif
|
||||
}
|
||||
#else /* TARGET_ABI_BITS == 32 */
|
||||
static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
|
||||
{
|
||||
return word0;
|
||||
}
|
||||
#endif /* TARGET_ABI_BITS != 32 */
|
||||
|
||||
/**
|
||||
* preexit_cleanup: housekeeping before the guest exits
|
||||
*
|
||||
|
@ -69,7 +69,11 @@ static void save_window(CPUSPARCState *env)
|
||||
save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
|
||||
env->wim = new_wim;
|
||||
#else
|
||||
save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
|
||||
/*
|
||||
* cansave is zero if the spill trap handler is triggered by `save` and
|
||||
* nonzero if triggered by a `flushw`
|
||||
*/
|
||||
save_window_offset(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
|
||||
env->cansave++;
|
||||
env->canrestore--;
|
||||
#endif
|
||||
|
@ -19,7 +19,9 @@ struct syscallname {
|
||||
void (*call)(const struct syscallname *,
|
||||
abi_long, abi_long, abi_long,
|
||||
abi_long, abi_long, abi_long);
|
||||
void (*result)(const struct syscallname *, abi_long);
|
||||
void (*result)(const struct syscallname *, abi_long,
|
||||
abi_long, abi_long, abi_long,
|
||||
abi_long, abi_long, abi_long);
|
||||
};
|
||||
|
||||
#ifdef __GNUC__
|
||||
@ -631,18 +633,12 @@ print_clockid(int clockid, int last)
|
||||
|
||||
/* select */
|
||||
#ifdef TARGET_NR__newselect
|
||||
static long newselect_arg1 = 0;
|
||||
static long newselect_arg2 = 0;
|
||||
static long newselect_arg3 = 0;
|
||||
static long newselect_arg4 = 0;
|
||||
static long newselect_arg5 = 0;
|
||||
|
||||
static void
|
||||
print_newselect(const struct syscallname *name,
|
||||
abi_long arg1, abi_long arg2, abi_long arg3,
|
||||
abi_long arg4, abi_long arg5, abi_long arg6)
|
||||
{
|
||||
qemu_log("%s(" TARGET_ABI_FMT_ld ",", name->name, arg1);
|
||||
print_syscall_prologue(name);
|
||||
print_fdset(arg1, arg2);
|
||||
qemu_log(",");
|
||||
print_fdset(arg1, arg3);
|
||||
@ -650,14 +646,7 @@ print_newselect(const struct syscallname *name,
|
||||
print_fdset(arg1, arg4);
|
||||
qemu_log(",");
|
||||
print_timeval(arg5, 1);
|
||||
qemu_log(")");
|
||||
|
||||
/* save for use in the return output function below */
|
||||
newselect_arg1=arg1;
|
||||
newselect_arg2=arg2;
|
||||
newselect_arg3=arg3;
|
||||
newselect_arg4=arg4;
|
||||
newselect_arg5=arg5;
|
||||
print_syscall_epilogue(name);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -736,17 +725,29 @@ print_ipc(const struct syscallname *name,
|
||||
*/
|
||||
|
||||
static void
|
||||
print_syscall_ret_addr(const struct syscallname *name, abi_long ret)
|
||||
print_syscall_err(abi_long ret)
|
||||
{
|
||||
const char *errstr = NULL;
|
||||
|
||||
qemu_log(" = ");
|
||||
if (ret < 0) {
|
||||
qemu_log("-1 errno=%d", errno);
|
||||
errstr = target_strerror(-ret);
|
||||
if (errstr) {
|
||||
qemu_log(" (%s)", errstr);
|
||||
}
|
||||
}
|
||||
if (errstr) {
|
||||
qemu_log(" = -1 errno=%d (%s)\n", (int)-ret, errstr);
|
||||
} else {
|
||||
qemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret);
|
||||
}
|
||||
|
||||
static void
|
||||
print_syscall_ret_addr(const struct syscallname *name, abi_long ret,
|
||||
abi_long arg0, abi_long arg1, abi_long arg2,
|
||||
abi_long arg3, abi_long arg4, abi_long arg5)
|
||||
{
|
||||
print_syscall_err(ret);
|
||||
|
||||
if (ret >= 0) {
|
||||
qemu_log("0x" TARGET_ABI_FMT_lx "\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
@ -760,17 +761,25 @@ print_syscall_ret_raw(struct syscallname *name, abi_long ret)
|
||||
|
||||
#ifdef TARGET_NR__newselect
|
||||
static void
|
||||
print_syscall_ret_newselect(const struct syscallname *name, abi_long ret)
|
||||
print_syscall_ret_newselect(const struct syscallname *name, abi_long ret,
|
||||
abi_long arg0, abi_long arg1, abi_long arg2,
|
||||
abi_long arg3, abi_long arg4, abi_long arg5)
|
||||
{
|
||||
qemu_log(" = 0x" TARGET_ABI_FMT_lx " (", ret);
|
||||
print_fdset(newselect_arg1,newselect_arg2);
|
||||
qemu_log(",");
|
||||
print_fdset(newselect_arg1,newselect_arg3);
|
||||
qemu_log(",");
|
||||
print_fdset(newselect_arg1,newselect_arg4);
|
||||
qemu_log(",");
|
||||
print_timeval(newselect_arg5, 1);
|
||||
qemu_log(")\n");
|
||||
print_syscall_err(ret);
|
||||
|
||||
if (ret >= 0) {
|
||||
qemu_log(" = 0x" TARGET_ABI_FMT_lx " (", ret);
|
||||
print_fdset(arg0, arg1);
|
||||
qemu_log(",");
|
||||
print_fdset(arg0, arg2);
|
||||
qemu_log(",");
|
||||
print_fdset(arg0, arg3);
|
||||
qemu_log(",");
|
||||
print_timeval(arg4, 1);
|
||||
qemu_log(")");
|
||||
}
|
||||
|
||||
qemu_log("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -783,18 +792,13 @@ print_syscall_ret_newselect(const struct syscallname *name, abi_long ret)
|
||||
#define TARGET_TIME_ERROR 5 /* clock not synchronized */
|
||||
#ifdef TARGET_NR_adjtimex
|
||||
static void
|
||||
print_syscall_ret_adjtimex(const struct syscallname *name, abi_long ret)
|
||||
print_syscall_ret_adjtimex(const struct syscallname *name, abi_long ret,
|
||||
abi_long arg0, abi_long arg1, abi_long arg2,
|
||||
abi_long arg3, abi_long arg4, abi_long arg5)
|
||||
{
|
||||
const char *errstr = NULL;
|
||||
print_syscall_err(ret);
|
||||
|
||||
qemu_log(" = ");
|
||||
if (ret < 0) {
|
||||
qemu_log("-1 errno=%d", errno);
|
||||
errstr = target_strerror(-ret);
|
||||
if (errstr) {
|
||||
qemu_log(" (%s)", errstr);
|
||||
}
|
||||
} else {
|
||||
if (ret >= 0) {
|
||||
qemu_log(TARGET_ABI_FMT_ld, ret);
|
||||
switch (ret) {
|
||||
case TARGET_TIME_OK:
|
||||
@ -822,6 +826,78 @@ print_syscall_ret_adjtimex(const struct syscallname *name, abi_long ret)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NR_listxattr) || defined(TARGET_NR_llistxattr) \
|
||||
|| defined(TARGGET_NR_flistxattr)
|
||||
static void
|
||||
print_syscall_ret_listxattr(const struct syscallname *name, abi_long ret,
|
||||
abi_long arg0, abi_long arg1, abi_long arg2,
|
||||
abi_long arg3, abi_long arg4, abi_long arg5)
|
||||
{
|
||||
print_syscall_err(ret);
|
||||
|
||||
if (ret >= 0) {
|
||||
qemu_log(TARGET_ABI_FMT_ld, ret);
|
||||
qemu_log(" (list = ");
|
||||
if (arg1 != 0) {
|
||||
abi_long attr = arg1;
|
||||
while (ret) {
|
||||
if (attr != arg1) {
|
||||
qemu_log(",");
|
||||
}
|
||||
print_string(attr, 1);
|
||||
ret -= target_strlen(attr) + 1;
|
||||
attr += target_strlen(attr) + 1;
|
||||
}
|
||||
} else {
|
||||
qemu_log("NULL");
|
||||
}
|
||||
qemu_log(")");
|
||||
}
|
||||
|
||||
qemu_log("\n");
|
||||
}
|
||||
#define print_syscall_ret_llistxattr print_syscall_ret_listxattr
|
||||
#define print_syscall_ret_flistxattr print_syscall_ret_listxattr
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_NR_ioctl
|
||||
static void
|
||||
print_syscall_ret_ioctl(const struct syscallname *name, abi_long ret,
|
||||
abi_long arg0, abi_long arg1, abi_long arg2,
|
||||
abi_long arg3, abi_long arg4, abi_long arg5)
|
||||
{
|
||||
print_syscall_err(ret);
|
||||
|
||||
if (ret >= 0) {
|
||||
qemu_log(TARGET_ABI_FMT_ld, ret);
|
||||
|
||||
const IOCTLEntry *ie;
|
||||
const argtype *arg_type;
|
||||
void *argptr;
|
||||
int target_size;
|
||||
|
||||
for (ie = ioctl_entries; ie->target_cmd != 0; ie++) {
|
||||
if (ie->target_cmd == arg1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ie->target_cmd == arg1 &&
|
||||
(ie->access == IOC_R || ie->access == IOC_RW)) {
|
||||
arg_type = ie->arg_type;
|
||||
qemu_log(" (");
|
||||
arg_type++;
|
||||
target_size = thunk_type_size(arg_type, 0);
|
||||
argptr = lock_user(VERIFY_READ, arg2, target_size, 1);
|
||||
thunk_print(argptr, arg_type);
|
||||
unlock_user(argptr, arg2, target_size);
|
||||
qemu_log(")");
|
||||
}
|
||||
}
|
||||
qemu_log("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
UNUSED static struct flags access_flags[] = {
|
||||
FLAG_GENERIC(F_OK),
|
||||
FLAG_GENERIC(R_OK),
|
||||
@ -1097,6 +1173,26 @@ UNUSED static struct flags statx_mask[] = {
|
||||
FLAG_END,
|
||||
};
|
||||
|
||||
UNUSED static struct flags falloc_flags[] = {
|
||||
FLAG_GENERIC(FALLOC_FL_KEEP_SIZE),
|
||||
FLAG_GENERIC(FALLOC_FL_PUNCH_HOLE),
|
||||
#ifdef FALLOC_FL_NO_HIDE_STALE
|
||||
FLAG_GENERIC(FALLOC_FL_NO_HIDE_STALE),
|
||||
#endif
|
||||
#ifdef FALLOC_FL_COLLAPSE_RANGE
|
||||
FLAG_GENERIC(FALLOC_FL_COLLAPSE_RANGE),
|
||||
#endif
|
||||
#ifdef FALLOC_FL_ZERO_RANGE
|
||||
FLAG_GENERIC(FALLOC_FL_ZERO_RANGE),
|
||||
#endif
|
||||
#ifdef FALLOC_FL_INSERT_RANGE
|
||||
FLAG_GENERIC(FALLOC_FL_INSERT_RANGE),
|
||||
#endif
|
||||
#ifdef FALLOC_FL_UNSHARE_RANGE
|
||||
FLAG_GENERIC(FALLOC_FL_UNSHARE_RANGE),
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* print_xxx utility functions. These are used to print syscall
|
||||
* parameters in certain format. All of these have parameter
|
||||
@ -1353,6 +1449,18 @@ print_access(const struct syscallname *name,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_NR_acct
|
||||
static void
|
||||
print_acct(const struct syscallname *name,
|
||||
abi_long arg0, abi_long arg1, abi_long arg2,
|
||||
abi_long arg3, abi_long arg4, abi_long arg5)
|
||||
{
|
||||
print_syscall_prologue(name);
|
||||
print_string(arg0, 1);
|
||||
print_syscall_epilogue(name);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_NR_brk
|
||||
static void
|
||||
print_brk(const struct syscallname *name,
|
||||
@ -1402,6 +1510,21 @@ print_chmod(const struct syscallname *name,
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NR_chown) || defined(TARGET_NR_lchown)
|
||||
static void
|
||||
print_chown(const struct syscallname *name,
|
||||
abi_long arg0, abi_long arg1, abi_long arg2,
|
||||
abi_long arg3, abi_long arg4, abi_long arg5)
|
||||
{
|
||||
print_syscall_prologue(name);
|
||||
print_string(arg0, 0);
|
||||
print_raw_param("%d", arg1, 0);
|
||||
print_raw_param("%d", arg2, 1);
|
||||
print_syscall_epilogue(name);
|
||||
}
|
||||
#define print_lchown print_chown
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_NR_clock_adjtime
|
||||
static void
|
||||
print_clock_adjtime(const struct syscallname *name,
|
||||
@ -1487,6 +1610,26 @@ print_faccessat(const struct syscallname *name,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_NR_fallocate
|
||||
static void
|
||||
print_fallocate(const struct syscallname *name,
|
||||
abi_long arg0, abi_long arg1, abi_long arg2,
|
||||
abi_long arg3, abi_long arg4, abi_long arg5)
|
||||
{
|
||||
print_syscall_prologue(name);
|
||||
print_raw_param("%d", arg0, 0);
|
||||
print_flags(falloc_flags, arg1, 0);
|
||||
#if TARGET_ABI_BITS == 32
|
||||
print_raw_param("%" PRIu64, target_offset64(arg2, arg3), 0);
|
||||
print_raw_param("%" PRIu64, target_offset64(arg4, arg5), 1);
|
||||
#else
|
||||
print_raw_param(TARGET_ABI_FMT_ld, arg2, 0);
|
||||
print_raw_param(TARGET_ABI_FMT_ld, arg3, 1);
|
||||
#endif
|
||||
print_syscall_epilogue(name);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_NR_fchmodat
|
||||
static void
|
||||
print_fchmodat(const struct syscallname *name,
|
||||
@ -1617,6 +1760,92 @@ print_fcntl(const struct syscallname *name,
|
||||
#define print_fcntl64 print_fcntl
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_NR_fgetxattr
|
||||
static void
|
||||
print_fgetxattr(const struct syscallname *name,
|
||||
abi_long arg0, abi_long arg1, abi_long arg2,
|
||||
abi_long arg3, abi_long arg4, abi_long arg5)
|
||||
{
|
||||
print_syscall_prologue(name);
|
||||
print_raw_param("%d", arg0, 0);
|
||||
print_string(arg1, 0);
|
||||
print_pointer(arg2, 0);
|
||||
print_raw_param(TARGET_FMT_lu, arg3, 1);
|
||||
print_syscall_epilogue(name);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_NR_flistxattr
|
||||
static void
|
||||
print_flistxattr(const struct syscallname *name,
|
||||
abi_long arg0, abi_long arg1, abi_long arg2,
|
||||
abi_long arg3, abi_long arg4, abi_long arg5)
|
||||
{
|
||||
print_syscall_prologue(name);
|
||||
print_raw_param("%d", arg0, 0);
|
||||
print_pointer(arg1, 0);
|
||||
print_raw_param(TARGET_FMT_lu, arg2, 1);
|
||||
print_syscall_epilogue(name);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NR_getxattr) || defined(TARGET_NR_lgetxattr)
|
||||
static void
|
||||
print_getxattr(const struct syscallname *name,
|
||||
abi_long arg0, abi_long arg1, abi_long arg2,
|
||||
abi_long arg3, abi_long arg4, abi_long arg5)
|
||||
{
|
||||
print_syscall_prologue(name);
|
||||
print_string(arg0, 0);
|
||||
print_string(arg1, 0);
|
||||
print_pointer(arg2, 0);
|
||||
print_raw_param(TARGET_FMT_lu, arg3, 1);
|
||||
print_syscall_epilogue(name);
|
||||
}
|
||||
#define print_lgetxattr print_getxattr
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NR_listxattr) || defined(TARGET_NR_llistxattr)
|
||||
static void
|
||||
print_listxattr(const struct syscallname *name,
|
||||
abi_long arg0, abi_long arg1, abi_long arg2,
|
||||
abi_long arg3, abi_long arg4, abi_long arg5)
|
||||
{
|
||||
print_syscall_prologue(name);
|
||||
print_string(arg0, 0);
|
||||
print_pointer(arg1, 0);
|
||||
print_raw_param(TARGET_FMT_lu, arg2, 1);
|
||||
print_syscall_epilogue(name);
|
||||
}
|
||||
#define print_llistxattr print_listxattr
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NR_fremovexattr)
|
||||
static void
|
||||
print_fremovexattr(const struct syscallname *name,
|
||||
abi_long arg0, abi_long arg1, abi_long arg2,
|
||||
abi_long arg3, abi_long arg4, abi_long arg5)
|
||||
{
|
||||
print_syscall_prologue(name);
|
||||
print_raw_param("%d", arg0, 0);
|
||||
print_string(arg1, 1);
|
||||
print_syscall_epilogue(name);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NR_removexattr) || defined(TARGET_NR_lremovexattr)
|
||||
static void
|
||||
print_removexattr(const struct syscallname *name,
|
||||
abi_long arg0, abi_long arg1, abi_long arg2,
|
||||
abi_long arg3, abi_long arg4, abi_long arg5)
|
||||
{
|
||||
print_syscall_prologue(name);
|
||||
print_string(arg0, 0);
|
||||
print_string(arg1, 1);
|
||||
print_syscall_epilogue(name);
|
||||
}
|
||||
#define print_lremovexattr print_removexattr
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_NR_futimesat
|
||||
static void
|
||||
@ -1697,6 +1926,37 @@ print__llseek(const struct syscallname *name,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_NR_lseek
|
||||
static void
|
||||
print_lseek(const struct syscallname *name,
|
||||
abi_long arg0, abi_long arg1, abi_long arg2,
|
||||
abi_long arg3, abi_long arg4, abi_long arg5)
|
||||
{
|
||||
print_syscall_prologue(name);
|
||||
print_raw_param("%d", arg0, 0);
|
||||
print_raw_param(TARGET_ABI_FMT_ld, arg1, 0);
|
||||
switch (arg2) {
|
||||
case SEEK_SET:
|
||||
qemu_log("SEEK_SET"); break;
|
||||
case SEEK_CUR:
|
||||
qemu_log("SEEK_CUR"); break;
|
||||
case SEEK_END:
|
||||
qemu_log("SEEK_END"); break;
|
||||
#ifdef SEEK_DATA
|
||||
case SEEK_DATA:
|
||||
qemu_log("SEEK_DATA"); break;
|
||||
#endif
|
||||
#ifdef SEEK_HOLE
|
||||
case SEEK_HOLE:
|
||||
qemu_log("SEEK_HOLE"); break;
|
||||
#endif
|
||||
default:
|
||||
print_raw_param("%#x", arg2, 1);
|
||||
}
|
||||
print_syscall_epilogue(name);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NR_socket)
|
||||
static void
|
||||
print_socket(const struct syscallname *name,
|
||||
@ -2804,6 +3064,75 @@ print_statx(const struct syscallname *name,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_NR_ioctl
|
||||
static void
|
||||
print_ioctl(const struct syscallname *name,
|
||||
abi_long arg0, abi_long arg1, abi_long arg2,
|
||||
abi_long arg3, abi_long arg4, abi_long arg5)
|
||||
{
|
||||
print_syscall_prologue(name);
|
||||
print_raw_param("%d", arg0, 0);
|
||||
|
||||
const IOCTLEntry *ie;
|
||||
const argtype *arg_type;
|
||||
void *argptr;
|
||||
int target_size;
|
||||
|
||||
for (ie = ioctl_entries; ie->target_cmd != 0; ie++) {
|
||||
if (ie->target_cmd == arg1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ie->target_cmd == 0) {
|
||||
print_raw_param("%#x", arg1, 0);
|
||||
print_raw_param("%#x", arg2, 1);
|
||||
} else {
|
||||
qemu_log("%s", ie->name);
|
||||
arg_type = ie->arg_type;
|
||||
|
||||
if (arg_type[0] != TYPE_NULL) {
|
||||
qemu_log(",");
|
||||
|
||||
switch (arg_type[0]) {
|
||||
case TYPE_PTRVOID:
|
||||
print_pointer(arg2, 1);
|
||||
break;
|
||||
case TYPE_CHAR:
|
||||
case TYPE_SHORT:
|
||||
case TYPE_INT:
|
||||
print_raw_param("%d", arg2, 1);
|
||||
break;
|
||||
case TYPE_LONG:
|
||||
print_raw_param(TARGET_ABI_FMT_ld, arg2, 1);
|
||||
break;
|
||||
case TYPE_ULONG:
|
||||
print_raw_param(TARGET_ABI_FMT_lu, arg2, 1);
|
||||
break;
|
||||
case TYPE_PTR:
|
||||
switch (ie->access) {
|
||||
case IOC_R:
|
||||
print_pointer(arg2, 1);
|
||||
break;
|
||||
case IOC_W:
|
||||
case IOC_RW:
|
||||
arg_type++;
|
||||
target_size = thunk_type_size(arg_type, 0);
|
||||
argptr = lock_user(VERIFY_READ, arg2, target_size, 1);
|
||||
thunk_print(argptr, arg_type);
|
||||
unlock_user(argptr, arg2, target_size);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
}
|
||||
print_syscall_epilogue(name);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* An array of all of the syscalls we know about
|
||||
*/
|
||||
@ -2847,25 +3176,25 @@ print_syscall(int num,
|
||||
|
||||
|
||||
void
|
||||
print_syscall_ret(int num, abi_long ret)
|
||||
print_syscall_ret(int num, abi_long ret,
|
||||
abi_long arg1, abi_long arg2, abi_long arg3,
|
||||
abi_long arg4, abi_long arg5, abi_long arg6)
|
||||
{
|
||||
int i;
|
||||
const char *errstr = NULL;
|
||||
|
||||
for(i=0;i<nsyscalls;i++)
|
||||
if( scnames[i].nr == num ) {
|
||||
if( scnames[i].result != NULL ) {
|
||||
scnames[i].result(&scnames[i], ret);
|
||||
scnames[i].result(&scnames[i], ret,
|
||||
arg1, arg2, arg3,
|
||||
arg4, arg5, arg6);
|
||||
} else {
|
||||
if (ret < 0) {
|
||||
errstr = target_strerror(-ret);
|
||||
}
|
||||
if (errstr) {
|
||||
qemu_log(" = -1 errno=" TARGET_ABI_FMT_ld " (%s)\n",
|
||||
-ret, errstr);
|
||||
} else {
|
||||
qemu_log(" = " TARGET_ABI_FMT_ld "\n", ret);
|
||||
print_syscall_err(ret);
|
||||
|
||||
if (ret >= 0) {
|
||||
qemu_log(TARGET_ABI_FMT_ld, ret);
|
||||
}
|
||||
qemu_log("\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
{ TARGET_NR_access, "access" , NULL, print_access, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_acct
|
||||
{ TARGET_NR_acct, "acct" , NULL, NULL, NULL },
|
||||
{ TARGET_NR_acct, "acct" , NULL, print_acct, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_add_key
|
||||
{ TARGET_NR_add_key, "add_key" , NULL, NULL, NULL },
|
||||
@ -71,7 +71,7 @@
|
||||
{ TARGET_NR_chmod, "chmod" , NULL, print_chmod, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_chown
|
||||
{ TARGET_NR_chown, "chown" , NULL, NULL, NULL },
|
||||
{ TARGET_NR_chown, "chown" , NULL, print_chown, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_chown32
|
||||
{ TARGET_NR_chown32, "chown32" , NULL, NULL, NULL },
|
||||
@ -182,7 +182,7 @@
|
||||
{ TARGET_NR_fadvise64_64, "fadvise64_64" , NULL, NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_fallocate
|
||||
{ TARGET_NR_fallocate, "fallocate" , NULL, NULL, NULL },
|
||||
{ TARGET_NR_fallocate, "fallocate" , NULL, print_fallocate, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_fanotify_init
|
||||
{ TARGET_NR_fanotify_init, "fanotify_init" , NULL, NULL, NULL },
|
||||
@ -215,16 +215,17 @@
|
||||
{ TARGET_NR_fcntl64, "fcntl64" , NULL, print_fcntl64, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_fdatasync
|
||||
{ TARGET_NR_fdatasync, "fdatasync" , NULL, NULL, NULL },
|
||||
{ TARGET_NR_fdatasync, "fdatasync" , "%s(%d)", NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_fgetxattr
|
||||
{ TARGET_NR_fgetxattr, "fgetxattr" , NULL, NULL, NULL },
|
||||
{ TARGET_NR_fgetxattr, "fgetxattr" , NULL, print_fgetxattr, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_finit_module
|
||||
{ TARGET_NR_finit_module, "finit_module" , NULL, NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_flistxattr
|
||||
{ TARGET_NR_flistxattr, "flistxattr" , NULL, NULL, NULL },
|
||||
{ TARGET_NR_flistxattr, "flistxattr" , NULL, print_flistxattr,
|
||||
print_syscall_ret_flistxattr},
|
||||
#endif
|
||||
#ifdef TARGET_NR_flock
|
||||
{ TARGET_NR_flock, "flock" , NULL, NULL, NULL },
|
||||
@ -233,7 +234,7 @@
|
||||
{ TARGET_NR_fork, "fork" , "%s()", NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_fremovexattr
|
||||
{ TARGET_NR_fremovexattr, "fremovexattr" , NULL, NULL, NULL },
|
||||
{ TARGET_NR_fremovexattr, "fremovexattr" , NULL, print_fremovexattr, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_fsetxattr
|
||||
{ TARGET_NR_fsetxattr, "fsetxattr" , NULL, NULL, NULL },
|
||||
@ -251,7 +252,7 @@
|
||||
{ TARGET_NR_fstatfs64, "fstatfs64" , "%s(%d,%p)", NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_fsync
|
||||
{ TARGET_NR_fsync, "fsync" , NULL, NULL, NULL },
|
||||
{ TARGET_NR_fsync, "fsync" , "%s(%d)", NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_ftime
|
||||
{ TARGET_NR_ftime, "ftime" , NULL, NULL, NULL },
|
||||
@ -396,7 +397,7 @@
|
||||
{ TARGET_NR_getuid32, "getuid32" , NULL, NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_getxattr
|
||||
{ TARGET_NR_getxattr, "getxattr" , NULL, NULL, NULL },
|
||||
{ TARGET_NR_getxattr, "getxattr" , NULL, print_getxattr, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_getxgid
|
||||
{ TARGET_NR_getxgid, "getxgid" , NULL, NULL, NULL },
|
||||
@ -432,7 +433,8 @@
|
||||
{ TARGET_NR_io_cancel, "io_cancel" , NULL, NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_ioctl
|
||||
{ TARGET_NR_ioctl, "ioctl" , "%s(%d,%#x,%#x)", NULL, NULL },
|
||||
{ TARGET_NR_ioctl, "ioctl" , NULL, print_ioctl,
|
||||
print_syscall_ret_ioctl},
|
||||
#endif
|
||||
#ifdef TARGET_NR_io_destroy
|
||||
{ TARGET_NR_io_destroy, "io_destroy" , NULL, NULL, NULL },
|
||||
@ -474,13 +476,13 @@
|
||||
{ TARGET_NR_kill, "kill", NULL, print_kill, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_lchown
|
||||
{ TARGET_NR_lchown, "lchown" , NULL, NULL, NULL },
|
||||
{ TARGET_NR_lchown, "lchown" , NULL, print_lchown, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_lchown32
|
||||
{ TARGET_NR_lchown32, "lchown32" , NULL, NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_lgetxattr
|
||||
{ TARGET_NR_lgetxattr, "lgetxattr" , NULL, NULL, NULL },
|
||||
{ TARGET_NR_lgetxattr, "lgetxattr" , NULL, print_lgetxattr, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_link
|
||||
{ TARGET_NR_link, "link" , NULL, print_link, NULL },
|
||||
@ -492,13 +494,15 @@
|
||||
{ TARGET_NR_Linux, "Linux" , NULL, NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_listen
|
||||
{ TARGET_NR_listen, "listen" , NULL, NULL, NULL },
|
||||
{ TARGET_NR_listen, "listen" , "%s(%d,%d)", NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_listxattr
|
||||
{ TARGET_NR_listxattr, "listxattr" , NULL, NULL, NULL },
|
||||
{ TARGET_NR_listxattr, "listxattr" , NULL, print_listxattr,
|
||||
print_syscall_ret_listxattr},
|
||||
#endif
|
||||
#ifdef TARGET_NR_llistxattr
|
||||
{ TARGET_NR_llistxattr, "llistxattr" , NULL, NULL, NULL },
|
||||
{ TARGET_NR_llistxattr, "llistxattr" , NULL, print_llistxattr,
|
||||
print_syscall_ret_llistxattr},
|
||||
#endif
|
||||
#ifdef TARGET_NR__llseek
|
||||
{ TARGET_NR__llseek, "_llseek" , NULL, print__llseek, NULL },
|
||||
@ -510,10 +514,10 @@
|
||||
{ TARGET_NR_lookup_dcookie, "lookup_dcookie" , NULL, NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_lremovexattr
|
||||
{ TARGET_NR_lremovexattr, "lremovexattr" , NULL, NULL, NULL },
|
||||
{ TARGET_NR_lremovexattr, "lremovexattr" , NULL, print_lremovexattr, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_lseek
|
||||
{ TARGET_NR_lseek, "lseek" , NULL, NULL, NULL },
|
||||
{ TARGET_NR_lseek, "lseek" , NULL, print_lseek, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_lsetxattr
|
||||
{ TARGET_NR_lsetxattr, "lsetxattr" , NULL, NULL, NULL },
|
||||
@ -1116,7 +1120,7 @@
|
||||
{ TARGET_NR_remap_file_pages, "remap_file_pages" , NULL, NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_removexattr
|
||||
{ TARGET_NR_removexattr, "removexattr" , NULL, NULL, NULL },
|
||||
{ TARGET_NR_removexattr, "removexattr" , NULL, print_removexattr, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_rename
|
||||
{ TARGET_NR_rename, "rename" , NULL, print_rename, NULL },
|
||||
|
@ -112,6 +112,9 @@
|
||||
#include <linux/if_alg.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <sound/asound.h>
|
||||
#ifdef HAVE_DRM_H
|
||||
#include <libdrm/drm.h>
|
||||
#endif
|
||||
#include "linux_loop.h"
|
||||
#include "uname.h"
|
||||
|
||||
@ -4478,24 +4481,6 @@ STRUCT_MAX
|
||||
#undef STRUCT
|
||||
#undef STRUCT_SPECIAL
|
||||
|
||||
typedef struct IOCTLEntry IOCTLEntry;
|
||||
|
||||
typedef abi_long do_ioctl_fn(const IOCTLEntry *ie, uint8_t *buf_temp,
|
||||
int fd, int cmd, abi_long arg);
|
||||
|
||||
struct IOCTLEntry {
|
||||
int target_cmd;
|
||||
unsigned int host_cmd;
|
||||
const char *name;
|
||||
int access;
|
||||
do_ioctl_fn *do_ioctl;
|
||||
const argtype arg_type[5];
|
||||
};
|
||||
|
||||
#define IOC_R 0x0001
|
||||
#define IOC_W 0x0002
|
||||
#define IOC_RW (IOC_R | IOC_W)
|
||||
|
||||
#define MAX_STRUCT_SIZE 4096
|
||||
|
||||
#ifdef CONFIG_FIEMAP
|
||||
@ -5276,7 +5261,102 @@ static abi_long do_ioctl_tiocgptpeer(const IOCTLEntry *ie, uint8_t *buf_temp,
|
||||
}
|
||||
#endif
|
||||
|
||||
static IOCTLEntry ioctl_entries[] = {
|
||||
#ifdef HAVE_DRM_H
|
||||
|
||||
static void unlock_drm_version(struct drm_version *host_ver,
|
||||
struct target_drm_version *target_ver,
|
||||
bool copy)
|
||||
{
|
||||
unlock_user(host_ver->name, target_ver->name,
|
||||
copy ? host_ver->name_len : 0);
|
||||
unlock_user(host_ver->date, target_ver->date,
|
||||
copy ? host_ver->date_len : 0);
|
||||
unlock_user(host_ver->desc, target_ver->desc,
|
||||
copy ? host_ver->desc_len : 0);
|
||||
}
|
||||
|
||||
static inline abi_long target_to_host_drmversion(struct drm_version *host_ver,
|
||||
struct target_drm_version *target_ver)
|
||||
{
|
||||
memset(host_ver, 0, sizeof(*host_ver));
|
||||
|
||||
__get_user(host_ver->name_len, &target_ver->name_len);
|
||||
if (host_ver->name_len) {
|
||||
host_ver->name = lock_user(VERIFY_WRITE, target_ver->name,
|
||||
target_ver->name_len, 0);
|
||||
if (!host_ver->name) {
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
__get_user(host_ver->date_len, &target_ver->date_len);
|
||||
if (host_ver->date_len) {
|
||||
host_ver->date = lock_user(VERIFY_WRITE, target_ver->date,
|
||||
target_ver->date_len, 0);
|
||||
if (!host_ver->date) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
__get_user(host_ver->desc_len, &target_ver->desc_len);
|
||||
if (host_ver->desc_len) {
|
||||
host_ver->desc = lock_user(VERIFY_WRITE, target_ver->desc,
|
||||
target_ver->desc_len, 0);
|
||||
if (!host_ver->desc) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
unlock_drm_version(host_ver, target_ver, false);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static inline void host_to_target_drmversion(
|
||||
struct target_drm_version *target_ver,
|
||||
struct drm_version *host_ver)
|
||||
{
|
||||
__put_user(host_ver->version_major, &target_ver->version_major);
|
||||
__put_user(host_ver->version_minor, &target_ver->version_minor);
|
||||
__put_user(host_ver->version_patchlevel, &target_ver->version_patchlevel);
|
||||
__put_user(host_ver->name_len, &target_ver->name_len);
|
||||
__put_user(host_ver->date_len, &target_ver->date_len);
|
||||
__put_user(host_ver->desc_len, &target_ver->desc_len);
|
||||
unlock_drm_version(host_ver, target_ver, true);
|
||||
}
|
||||
|
||||
static abi_long do_ioctl_drm(const IOCTLEntry *ie, uint8_t *buf_temp,
|
||||
int fd, int cmd, abi_long arg)
|
||||
{
|
||||
struct drm_version *ver;
|
||||
struct target_drm_version *target_ver;
|
||||
abi_long ret;
|
||||
|
||||
switch (ie->host_cmd) {
|
||||
case DRM_IOCTL_VERSION:
|
||||
if (!lock_user_struct(VERIFY_WRITE, target_ver, arg, 0)) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
ver = (struct drm_version *)buf_temp;
|
||||
ret = target_to_host_drmversion(ver, target_ver);
|
||||
if (!is_error(ret)) {
|
||||
ret = get_errno(safe_ioctl(fd, ie->host_cmd, ver));
|
||||
if (is_error(ret)) {
|
||||
unlock_drm_version(ver, target_ver, false);
|
||||
} else {
|
||||
host_to_target_drmversion(target_ver, ver);
|
||||
}
|
||||
}
|
||||
unlock_user_struct(target_ver, arg, 0);
|
||||
return ret;
|
||||
}
|
||||
return -TARGET_ENOSYS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
IOCTLEntry ioctl_entries[] = {
|
||||
#define IOCTL(cmd, access, ...) \
|
||||
{ TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
|
||||
#define IOCTL_SPECIAL(cmd, access, dofn, ...) \
|
||||
@ -6614,22 +6694,6 @@ void syscall_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
#if TARGET_ABI_BITS == 32
|
||||
static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
|
||||
{
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
return ((uint64_t)word0 << 32) | word1;
|
||||
#else
|
||||
return ((uint64_t)word1 << 32) | word0;
|
||||
#endif
|
||||
}
|
||||
#else /* TARGET_ABI_BITS == 32 */
|
||||
static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
|
||||
{
|
||||
return word0;
|
||||
}
|
||||
#endif /* TARGET_ABI_BITS != 32 */
|
||||
|
||||
#ifdef TARGET_NR_truncate64
|
||||
static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
|
||||
abi_long arg2,
|
||||
@ -12467,7 +12531,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
arg5, arg6, arg7, arg8);
|
||||
|
||||
if (unlikely(qemu_loglevel_mask(LOG_STRACE))) {
|
||||
print_syscall_ret(num, ret);
|
||||
print_syscall_ret(num, ret, arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
}
|
||||
|
||||
record_syscall_return(cpu, num, ret);
|
||||
|
@ -1167,6 +1167,9 @@ struct target_rtc_pll_info {
|
||||
#define TARGET_DM_TARGET_MSG TARGET_IOWRU(0xfd, 0x0e)
|
||||
#define TARGET_DM_DEV_SET_GEOMETRY TARGET_IOWRU(0xfd, 0x0f)
|
||||
|
||||
/* drm ioctls */
|
||||
#define TARGET_DRM_IOCTL_VERSION TARGET_IOWRU('d', 0x00)
|
||||
|
||||
/* from asm/termbits.h */
|
||||
|
||||
#define TARGET_NCC 8
|
||||
@ -2598,6 +2601,18 @@ struct target_mq_attr {
|
||||
abi_long mq_curmsgs;
|
||||
};
|
||||
|
||||
struct target_drm_version {
|
||||
int version_major;
|
||||
int version_minor;
|
||||
int version_patchlevel;
|
||||
abi_ulong name_len;
|
||||
abi_ulong name;
|
||||
abi_ulong date_len;
|
||||
abi_ulong date;
|
||||
abi_ulong desc_len;
|
||||
abi_ulong desc;
|
||||
};
|
||||
|
||||
#include "socket.h"
|
||||
|
||||
#include "errno_defs.h"
|
||||
|
@ -137,10 +137,32 @@ STRUCT(snd_timer_params,
|
||||
TYPE_INT, /* filter */
|
||||
MK_ARRAY(TYPE_CHAR, 60)) /* reserved */
|
||||
|
||||
#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
|
||||
STRUCT(timeval,
|
||||
TYPE_LONG, /* tv_sec */
|
||||
TYPE_INT) /* tv_usec */
|
||||
|
||||
STRUCT(_kernel_sock_timeval,
|
||||
TYPE_LONG, /* tv_sec */
|
||||
TYPE_INT) /* tv_usec */
|
||||
#else
|
||||
STRUCT(timeval,
|
||||
TYPE_LONG, /* tv_sec */
|
||||
TYPE_LONG) /* tv_usec */
|
||||
|
||||
STRUCT(_kernel_sock_timeval,
|
||||
TYPE_LONGLONG, /* tv_sec */
|
||||
TYPE_LONGLONG) /* tv_usec */
|
||||
#endif
|
||||
|
||||
STRUCT(timespec,
|
||||
TYPE_LONG, /* tv_sec */
|
||||
TYPE_LONG) /* tv_nsec */
|
||||
|
||||
STRUCT(_kernel_timespec,
|
||||
TYPE_LONGLONG, /* tv_sec */
|
||||
TYPE_LONGLONG) /* tv_nsec */
|
||||
|
||||
STRUCT(snd_timer_status,
|
||||
MK_STRUCT(STRUCT_timespec), /* tstamp */
|
||||
TYPE_INT, /* resolution */
|
||||
@ -292,6 +314,17 @@ STRUCT(dm_target_versions,
|
||||
STRUCT(dm_target_msg,
|
||||
TYPE_ULONGLONG) /* sector */
|
||||
|
||||
STRUCT(drm_version,
|
||||
TYPE_INT, /* version_major */
|
||||
TYPE_INT, /* version_minor */
|
||||
TYPE_INT, /* version_patchlevel */
|
||||
TYPE_ULONG, /* name_len */
|
||||
TYPE_PTRVOID, /* name */
|
||||
TYPE_ULONG, /* date_len */
|
||||
TYPE_PTRVOID, /* date */
|
||||
TYPE_ULONG, /* desc_len */
|
||||
TYPE_PTRVOID) /* desc */
|
||||
|
||||
STRUCT(file_clone_range,
|
||||
TYPE_LONGLONG, /* src_fd */
|
||||
TYPE_ULONGLONG, /* src_offset */
|
||||
|
@ -3663,6 +3663,8 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
|
||||
#endif
|
||||
gen_store_gpr(dc, rd, cpu_tmp0);
|
||||
break;
|
||||
#endif
|
||||
#if defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)
|
||||
} else if (xop == 0x2b) { /* rdtbr / V9 flushw */
|
||||
#ifdef TARGET_SPARC64
|
||||
gen_helper_flushw(cpu_env);
|
||||
|
154
thunk.c
154
thunk.c
@ -271,6 +271,160 @@ const argtype *thunk_convert(void *dst, const void *src,
|
||||
return type_ptr;
|
||||
}
|
||||
|
||||
const argtype *thunk_print(void *arg, const argtype *type_ptr)
|
||||
{
|
||||
int type;
|
||||
|
||||
type = *type_ptr++;
|
||||
|
||||
switch (type) {
|
||||
case TYPE_CHAR:
|
||||
qemu_log("%c", *(uint8_t *)arg);
|
||||
break;
|
||||
case TYPE_SHORT:
|
||||
qemu_log("%" PRId16, tswap16(*(uint16_t *)arg));
|
||||
break;
|
||||
case TYPE_INT:
|
||||
qemu_log("%" PRId32, tswap32(*(uint32_t *)arg));
|
||||
break;
|
||||
case TYPE_LONGLONG:
|
||||
qemu_log("%" PRId64, tswap64(*(uint64_t *)arg));
|
||||
break;
|
||||
case TYPE_ULONGLONG:
|
||||
qemu_log("%" PRIu64, tswap64(*(uint64_t *)arg));
|
||||
break;
|
||||
#if HOST_LONG_BITS == 32 && TARGET_ABI_BITS == 32
|
||||
case TYPE_PTRVOID:
|
||||
qemu_log("0x%" PRIx32, tswap32(*(uint32_t *)arg));
|
||||
break;
|
||||
case TYPE_LONG:
|
||||
qemu_log("%" PRId32, tswap32(*(uint32_t *)arg));
|
||||
break;
|
||||
case TYPE_ULONG:
|
||||
qemu_log("%" PRIu32, tswap32(*(uint32_t *)arg));
|
||||
break;
|
||||
#elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 32
|
||||
case TYPE_PTRVOID:
|
||||
qemu_log("0x%" PRIx32, tswap32(*(uint64_t *)arg & 0xffffffff));
|
||||
break;
|
||||
case TYPE_LONG:
|
||||
qemu_log("%" PRId32, tswap32(*(uint64_t *)arg & 0xffffffff));
|
||||
break;
|
||||
case TYPE_ULONG:
|
||||
qemu_log("%" PRIu32, tswap32(*(uint64_t *)arg & 0xffffffff));
|
||||
break;
|
||||
#elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 64
|
||||
case TYPE_PTRVOID:
|
||||
qemu_log("0x%" PRIx64, tswap64(*(uint64_t *)arg));
|
||||
break;
|
||||
case TYPE_LONG:
|
||||
qemu_log("%" PRId64, tswap64(*(uint64_t *)arg));
|
||||
break;
|
||||
case TYPE_ULONG:
|
||||
qemu_log("%" PRIu64, tswap64(*(uint64_t *)arg));
|
||||
break;
|
||||
#else
|
||||
case TYPE_PTRVOID:
|
||||
qemu_log("0x%" PRIx64, tswap64(*(uint64_t *)arg));
|
||||
break;
|
||||
case TYPE_LONG:
|
||||
qemu_log("%" PRId64, tswap64(*(uint64_t *)arg));
|
||||
break;
|
||||
case TYPE_ULONG:
|
||||
qemu_log("%" PRIu64, tswap64(*(uint64_t *)arg));
|
||||
break;
|
||||
#endif
|
||||
case TYPE_OLDDEVT:
|
||||
{
|
||||
uint64_t val = 0;
|
||||
switch (thunk_type_size(type_ptr - 1, 1)) {
|
||||
case 2:
|
||||
val = *(uint16_t *)arg;
|
||||
break;
|
||||
case 4:
|
||||
val = *(uint32_t *)arg;
|
||||
break;
|
||||
case 8:
|
||||
val = *(uint64_t *)arg;
|
||||
break;
|
||||
}
|
||||
switch (thunk_type_size(type_ptr - 1, 0)) {
|
||||
case 2:
|
||||
qemu_log("%" PRIu16, tswap16(val));
|
||||
break;
|
||||
case 4:
|
||||
qemu_log("%" PRIu32, tswap32(val));
|
||||
break;
|
||||
case 8:
|
||||
qemu_log("%" PRIu64, tswap64(val));
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TYPE_ARRAY:
|
||||
{
|
||||
int i, array_length, arg_size;
|
||||
uint8_t *a;
|
||||
int is_string = 0;
|
||||
|
||||
array_length = *type_ptr++;
|
||||
arg_size = thunk_type_size(type_ptr, 0);
|
||||
a = arg;
|
||||
|
||||
if (*type_ptr == TYPE_CHAR) {
|
||||
qemu_log("\"");
|
||||
is_string = 1;
|
||||
} else {
|
||||
qemu_log("[");
|
||||
}
|
||||
|
||||
for (i = 0; i < array_length; i++) {
|
||||
if (i > 0 && !is_string) {
|
||||
qemu_log(",");
|
||||
}
|
||||
thunk_print(a, type_ptr);
|
||||
a += arg_size;
|
||||
}
|
||||
|
||||
if (is_string) {
|
||||
qemu_log("\"");
|
||||
} else {
|
||||
qemu_log("]");
|
||||
}
|
||||
|
||||
type_ptr = thunk_type_next(type_ptr);
|
||||
}
|
||||
break;
|
||||
case TYPE_STRUCT:
|
||||
{
|
||||
int i;
|
||||
const StructEntry *se;
|
||||
uint8_t *a;
|
||||
const argtype *field_types;
|
||||
const int *arg_offsets;
|
||||
|
||||
se = struct_entries + *type_ptr++;
|
||||
a = arg;
|
||||
|
||||
field_types = se->field_types;
|
||||
arg_offsets = se->field_offsets[0];
|
||||
|
||||
qemu_log("{");
|
||||
for (i = 0; i < se->nb_fields; i++) {
|
||||
if (i > 0) {
|
||||
qemu_log(",");
|
||||
}
|
||||
field_types = thunk_print(a + arg_offsets[i], field_types);
|
||||
}
|
||||
qemu_log("}");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
return type_ptr;
|
||||
}
|
||||
|
||||
/* from em86 */
|
||||
|
||||
/* Utility function: Table-driven functions to translate bitmasks
|
||||
|
Loading…
Reference in New Issue
Block a user