linux-user: translate the result of getsockopt SO_TYPE

QEMU previously passed the result of the host syscall directly to the
target program. This is a problem if the host & target have different
representations of socket types, as is the case when running a MIPS
target program on an x86 host. Introduce a host_to_target_sock_type
helper function mirroring the existing target_to_host_sock_type, and
call it to translate the value provided by getsockopt when called for
the SO_TYPE option.

Signed-off-by: Paul Burton <paul@archlinuxmips.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
This commit is contained in:
Paul Burton 2014-06-22 11:25:33 +01:00 committed by Riku Voipio
parent 76b9424550
commit 8289d11281
1 changed files with 34 additions and 0 deletions

View File

@ -592,6 +592,37 @@ char *target_strerror(int err)
return strerror(target_to_host_errno(err));
}
static inline int host_to_target_sock_type(int host_type)
{
int target_type;
switch (host_type & 0xf /* SOCK_TYPE_MASK */) {
case SOCK_DGRAM:
target_type = TARGET_SOCK_DGRAM;
break;
case SOCK_STREAM:
target_type = TARGET_SOCK_STREAM;
break;
default:
target_type = host_type & 0xf /* SOCK_TYPE_MASK */;
break;
}
#if defined(SOCK_CLOEXEC)
if (host_type & SOCK_CLOEXEC) {
target_type |= TARGET_SOCK_CLOEXEC;
}
#endif
#if defined(SOCK_NONBLOCK)
if (host_type & SOCK_NONBLOCK) {
target_type |= TARGET_SOCK_NONBLOCK;
}
#endif
return target_type;
}
static abi_ulong target_brk;
static abi_ulong target_original_brk;
static abi_ulong brk_page;
@ -1636,6 +1667,9 @@ static abi_long do_getsockopt(int sockfd, int level, int optname,
ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
if (ret < 0)
return ret;
if (optname == SO_TYPE) {
val = host_to_target_sock_type(val);
}
if (len > lv)
len = lv;
if (len == 4) {