aboutsummaryrefslogtreecommitdiff
path: root/linux-user
diff options
context:
space:
mode:
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/elfload.c37
-rw-r--r--linux-user/fd-trans.c9
-rw-r--r--linux-user/nios2/cpu_loop.c6
-rw-r--r--linux-user/strace.c12
-rw-r--r--linux-user/strace.list2
-rw-r--r--linux-user/syscall.c53
6 files changed, 97 insertions, 22 deletions
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 6e8762b40d..c1a26021f8 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -500,13 +500,48 @@ static uint32_t get_elf_hwcap2(void)
#undef GET_FEATURE
#undef GET_FEATURE_ID
+#define ELF_PLATFORM get_elf_platform()
+
+static const char *get_elf_platform(void)
+{
+ CPUARMState *env = thread_cpu->env_ptr;
+
+#ifdef TARGET_WORDS_BIGENDIAN
+# define END "b"
+#else
+# define END "l"
+#endif
+
+ if (arm_feature(env, ARM_FEATURE_V8)) {
+ return "v8" END;
+ } else if (arm_feature(env, ARM_FEATURE_V7)) {
+ if (arm_feature(env, ARM_FEATURE_M)) {
+ return "v7m" END;
+ } else {
+ return "v7" END;
+ }
+ } else if (arm_feature(env, ARM_FEATURE_V6)) {
+ return "v6" END;
+ } else if (arm_feature(env, ARM_FEATURE_V5)) {
+ return "v5" END;
+ } else {
+ return "v4" END;
+ }
+
+#undef END
+}
+
#else
/* 64 bit ARM definitions */
#define ELF_START_MMAP 0x80000000
#define ELF_ARCH EM_AARCH64
#define ELF_CLASS ELFCLASS64
-#define ELF_PLATFORM "aarch64"
+#ifdef TARGET_WORDS_BIGENDIAN
+# define ELF_PLATFORM "aarch64_be"
+#else
+# define ELF_PLATFORM "aarch64"
+#endif
static inline void init_thread(struct target_pt_regs *regs,
struct image_info *infop)
diff --git a/linux-user/fd-trans.c b/linux-user/fd-trans.c
index 30425c9df6..612819c1b1 100644
--- a/linux-user/fd-trans.c
+++ b/linux-user/fd-trans.c
@@ -75,6 +75,8 @@ enum {
QEMU_IFLA_BR_MCAST_STATS_ENABLED,
QEMU_IFLA_BR_MCAST_IGMP_VERSION,
QEMU_IFLA_BR_MCAST_MLD_VERSION,
+ QEMU_IFLA_BR_VLAN_STATS_PER_PORT,
+ QEMU_IFLA_BR_MULTI_BOOLOPT,
QEMU___IFLA_BR_MAX,
};
@@ -438,6 +440,7 @@ static abi_long host_to_target_data_bridge_nlattr(struct nlattr *nlattr,
case QEMU_IFLA_BR_MCAST_STATS_ENABLED:
case QEMU_IFLA_BR_MCAST_IGMP_VERSION:
case QEMU_IFLA_BR_MCAST_MLD_VERSION:
+ case QEMU_IFLA_BR_VLAN_STATS_PER_PORT:
break;
/* uint16_t */
case QEMU_IFLA_BR_PRIORITY:
@@ -543,6 +546,12 @@ static abi_long host_to_target_slave_data_bridge_nlattr(struct nlattr *nlattr,
case QEMU_IFLA_BRPORT_ROOT_ID:
case QEMU_IFLA_BRPORT_BRIDGE_ID:
break;
+ /* br_boolopt_multi { uint32_t, uint32_t } */
+ case QEMU_IFLA_BR_MULTI_BOOLOPT:
+ u32 = NLA_DATA(nlattr);
+ u32[0] = tswap32(u32[0]); /* optval */
+ u32[1] = tswap32(u32[1]); /* optmask */
+ break;
default:
gemu_log("Unknown QEMU_IFLA_BRPORT type %d\n", nlattr->nla_type);
break;
diff --git a/linux-user/nios2/cpu_loop.c b/linux-user/nios2/cpu_loop.c
index b96b1aa119..5aa1eca740 100644
--- a/linux-user/nios2/cpu_loop.c
+++ b/linux-user/nios2/cpu_loop.c
@@ -73,6 +73,12 @@ void cpu_loop(CPUNios2State *env)
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break;
}
+ case EXCP_DEBUG:
+ info.si_signo = TARGET_SIGTRAP;
+ info.si_errno = 0;
+ info.si_code = TARGET_TRAP_BRKPT;
+ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ break;
case 0xaa:
switch (env->regs[R_PC]) {
/*case 0x1000:*/ /* TODO:__kuser_helper_version */
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 7318392e57..6f72a74c09 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1235,6 +1235,18 @@ print_chdir(const struct syscallname *name,
}
#endif
+#ifdef TARGET_NR_chroot
+static void
+print_chroot(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_chmod
static void
print_chmod(const struct syscallname *name,
diff --git a/linux-user/strace.list b/linux-user/strace.list
index ff8bb19f5f..db21ce4177 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -77,7 +77,7 @@
{ TARGET_NR_chown32, "chown32" , NULL, NULL, NULL },
#endif
#ifdef TARGET_NR_chroot
-{ TARGET_NR_chroot, "chroot" , NULL, NULL, NULL },
+{ TARGET_NR_chroot, "chroot" , NULL, print_chroot, NULL },
#endif
#ifdef TARGET_NR_clock_adjtime
{ TARGET_NR_clock_adjtime, "clock_adjtime" , NULL, print_clock_adjtime, NULL },
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 5bbb72f3d5..208fd1813d 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -2759,6 +2759,7 @@ static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
}
if (!is_error(ret)) {
msgp->msg_namelen = tswap32(msg.msg_namelen);
+ msgp->msg_flags = tswap32(msg.msg_flags);
if (msg.msg_name != NULL && msg.msg_name != (void *)-1) {
ret = host_to_target_sockaddr(tswapal(msgp->msg_name),
msg.msg_name, msg.msg_namelen);
@@ -2846,7 +2847,7 @@ static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec,
static abi_long do_accept4(int fd, abi_ulong target_addr,
abi_ulong target_addrlen_addr, int flags)
{
- socklen_t addrlen;
+ socklen_t addrlen, ret_addrlen;
void *addr;
abi_long ret;
int host_flags;
@@ -2870,11 +2871,13 @@ static abi_long do_accept4(int fd, abi_ulong target_addr,
addr = alloca(addrlen);
- ret = get_errno(safe_accept4(fd, addr, &addrlen, host_flags));
+ ret_addrlen = addrlen;
+ ret = get_errno(safe_accept4(fd, addr, &ret_addrlen, host_flags));
if (!is_error(ret)) {
- host_to_target_sockaddr(target_addr, addr, addrlen);
- if (put_user_u32(addrlen, target_addrlen_addr))
+ host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
+ if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
ret = -TARGET_EFAULT;
+ }
}
return ret;
}
@@ -2883,7 +2886,7 @@ static abi_long do_accept4(int fd, abi_ulong target_addr,
static abi_long do_getpeername(int fd, abi_ulong target_addr,
abi_ulong target_addrlen_addr)
{
- socklen_t addrlen;
+ socklen_t addrlen, ret_addrlen;
void *addr;
abi_long ret;
@@ -2899,11 +2902,13 @@ static abi_long do_getpeername(int fd, abi_ulong target_addr,
addr = alloca(addrlen);
- ret = get_errno(getpeername(fd, addr, &addrlen));
+ ret_addrlen = addrlen;
+ ret = get_errno(getpeername(fd, addr, &ret_addrlen));
if (!is_error(ret)) {
- host_to_target_sockaddr(target_addr, addr, addrlen);
- if (put_user_u32(addrlen, target_addrlen_addr))
+ host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
+ if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
ret = -TARGET_EFAULT;
+ }
}
return ret;
}
@@ -2912,7 +2917,7 @@ static abi_long do_getpeername(int fd, abi_ulong target_addr,
static abi_long do_getsockname(int fd, abi_ulong target_addr,
abi_ulong target_addrlen_addr)
{
- socklen_t addrlen;
+ socklen_t addrlen, ret_addrlen;
void *addr;
abi_long ret;
@@ -2928,11 +2933,13 @@ static abi_long do_getsockname(int fd, abi_ulong target_addr,
addr = alloca(addrlen);
- ret = get_errno(getsockname(fd, addr, &addrlen));
+ ret_addrlen = addrlen;
+ ret = get_errno(getsockname(fd, addr, &ret_addrlen));
if (!is_error(ret)) {
- host_to_target_sockaddr(target_addr, addr, addrlen);
- if (put_user_u32(addrlen, target_addrlen_addr))
+ host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
+ if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
ret = -TARGET_EFAULT;
+ }
}
return ret;
}
@@ -3004,7 +3011,7 @@ static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
abi_ulong target_addr,
abi_ulong target_addrlen)
{
- socklen_t addrlen;
+ socklen_t addrlen, ret_addrlen;
void *addr;
void *host_msg;
abi_long ret;
@@ -3022,10 +3029,12 @@ static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
goto fail;
}
addr = alloca(addrlen);
+ ret_addrlen = addrlen;
ret = get_errno(safe_recvfrom(fd, host_msg, len, flags,
- addr, &addrlen));
+ addr, &ret_addrlen));
} else {
addr = NULL; /* To keep compiler quiet. */
+ addrlen = 0; /* To keep compiler quiet. */
ret = get_errno(safe_recvfrom(fd, host_msg, len, flags, NULL, 0));
}
if (!is_error(ret)) {
@@ -3038,8 +3047,9 @@ static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
}
}
if (target_addr) {
- host_to_target_sockaddr(target_addr, addr, addrlen);
- if (put_user_u32(addrlen, target_addrlen)) {
+ host_to_target_sockaddr(target_addr, addr,
+ MIN(addrlen, ret_addrlen));
+ if (put_user_u32(ret_addrlen, target_addrlen)) {
ret = -TARGET_EFAULT;
goto fail;
}
@@ -4723,8 +4733,8 @@ static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp,
const int *dst_offsets, *src_offsets;
int target_size;
void *argptr;
- abi_ulong *target_rt_dev_ptr;
- unsigned long *host_rt_dev_ptr;
+ abi_ulong *target_rt_dev_ptr = NULL;
+ unsigned long *host_rt_dev_ptr = NULL;
abi_long ret;
int i;
@@ -4770,6 +4780,9 @@ static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp,
unlock_user(argptr, arg, 0);
ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
+
+ assert(host_rt_dev_ptr != NULL);
+ assert(target_rt_dev_ptr != NULL);
if (*host_rt_dev_ptr != 0) {
unlock_user((void *)*host_rt_dev_ptr,
*target_rt_dev_ptr, 0);
@@ -6999,8 +7012,8 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
_exit(arg1);
return 0; /* avoid warning */
case TARGET_NR_read:
- if (arg3 == 0) {
- return 0;
+ if (arg2 == 0 && arg3 == 0) {
+ return get_errno(safe_read(arg1, 0, 0));
} else {
if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
return -TARGET_EFAULT;