qemu-devel
[Top][All Lists]
Advanced

[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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]