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:
Peter Maydell 2020-07-06 11:40:10 +01:00
commit 7623b5ba01
14 changed files with 781 additions and 115 deletions

View File

@ -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

View File

@ -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
View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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
*

View File

@ -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

View File

@ -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;
}

View File

@ -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 },

View File

@ -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);

View File

@ -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"

View File

@ -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 */

View File

@ -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
View File

@ -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