[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] Small patch for getdents syscall
From: |
Peter Maydell |
Subject: |
Re: [Qemu-devel] Small patch for getdents syscall |
Date: |
Mon, 13 Mar 2017 11:49:32 +0100 |
On 8 March 2017 at 00:40, Henry Wertz <address@hidden> wrote:
> I have a trivial, 1-line patch for getdents function; due to use of
> unsigned long, the struct on 64-bit and 32-bit systems is not the same.
> qemu is aware of this, however it currently only checks for a 32-bit target
> on 64-bit host case; in my case, I'm running 64-bit target on 32-bit host
> (x86-64 binaries on a 32-bit ARM).
>
> My use case for this patch, I have Android Studio on my (32-bit ARM)
> chromebook -- thank goodness I got the 4GB model! Since Android Studio is
> java, that worked; but it calls aapt from build tools. Up through 23.x.x
> (which is build for 32-bit x86) it worked. With 25.0.0 (and 24.x.x
> version) aapt is now built for 64-bit x86-64; it would give an odd error
> about a directory being invalid. By comparing strace between qemu and real
> x86-64, I found getdents was behaving differently. WIth this patch aapt
> completes.
>
> I really wasn't sure if this would be better this way ("if target != host")
> or if something like "if (target==32 && host==64) || (target==64 &&
> host==32)" would be preferrable.
> ---------------------------------------------------
>
> Signed-off-by: Henry Wertz <address@hidden>
>
> *** linux-user/syscall.c~ 2017-03-04 10:31:14.000000000 -0600
> --- linux-user/syscall.c 2017-03-07 17:08:24.615399116 -0600
> ***************
> *** 9913,9921 ****
> #endif
> #ifdef TARGET_NR_getdents
> case TARGET_NR_getdents:
> #ifdef __NR_getdents
> ! #if TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
> {
> struct target_dirent *target_dirp;
> struct linux_dirent *dirp;
> abi_long count = arg3;
> --- 9913,9921 ----
> #endif
> #ifdef TARGET_NR_getdents
> case TARGET_NR_getdents:
> #ifdef __NR_getdents
> ! #if TARGET_ABI_BITS != HOST_LONG_BITS
> {
> struct target_dirent *target_dirp;
> struct linux_dirent *dirp;
> abi_long count = arg3;
There is a theoretically better way to handle the 64-bit
guest on 32-bit host case: since here you know that the
guest dirent struct is bigger than the host dirent
struct you could read them directly into the guest buffer
and then convert in-place rather than having to malloc
a temporary buffer. The conversion code is a little
bit awkward though because you have to make sure you don't
overwrite host data you haven't read yet, so I think
you would need to start at the end of the buffer and
work backwards. This is basically fixing the #else
part of this code to work for guest > host as well
as for guest == host.
However, since 64-bit-on-32 is not exactly a very common
use case these days I think your patch is an OK fix for
things.
Reviewed-by: Peter Maydell <address@hidden>
PS: we prefer 'unified' format diffs; git format-patch
should produce those by default.
thanks
-- PMM