Patchwork Fix 64-bit off_t syscall argument passing in linux-user

login
register
mail settings
Submitter Tomasz Łukaszewski
Date March 25, 2010, 9:04 a.m.
Message ID <4BAB270E.1070201@cubiware.com>
Download mbox | patch
Permalink /patch/48506/
State New
Headers show

Comments

Tomasz Łukaszewski - March 25, 2010, 9:04 a.m.
Hello,

I am evaluating the possibility to use linux-user emulation in qemu for
automatic regression testing for some embedded linux projects in the
company I work for. I've encountered some problems with syscall interface
while testing mips(el), powerpc and arm code, and I am willing to fix them.
This is the first patch, I'd appeciate any comments.

Best regards,
Tomasz Lukaszewski




In 32-bit ABIs 64-bit arguments are passed in a pair of registers
(ra, rb), where ra is an odd numbered one. This patch fixes such
case for truncate64, ftruncate64, pread64 and pwrite64 for mips,
ppc and arm-eabi.
---
 linux-user/syscall.c |   64 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 62 insertions(+), 2 deletions(-)
Richard Henderson - March 25, 2010, 3:55 p.m.
On 03/25/2010 02:04 AM, Tomasz Łukaszewski wrote:
> +#if TARGET_ABI_BITS == 32
> +#ifdef TARGET_ARM
> +    if (((CPUARMState *)cpu_env)->eabi)
> +      {
> +        arg4 = arg5;
> +        arg5 = arg6;
> +      }
> +#endif
> +#if defined TARGET_PPC || defined TARGET_MIPS
> +    arg4 = arg5;
> +    arg5 = arg6;
> +#endif
> +#endif

I wonder if this sequence couldn't be encapsulated in a macro.  Something like

#if TARGET_ABI_BITS == 32
# if defined TARGET_ARM
#  define FIXUP_64BIT_ARGUMENT_PAIR(a,b,c)     \
    do {                                       \
        if (((CPUARMState *)cpu_env)->eabi) {  \
            a = b, b = c;                      \
        }                                      \
    } while (0)
# elif defined TARGET_PPC || defined TARGET_MIPS
#  define FIXUP_64BIT_ARGUMENT_PAIR(a,b,c)     \
    do { a = b, b = c; } while (0)
# endif
#endif
#ifndef FIXUP_64BIT_ARGUMENT_PAIR
# define FIXUP_64BIT_ARGUMENT_PAIR(a,b,c) \
    do { } while (0)
#endif


r~

Patch

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 80d8633..0bf146d 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -3922,6 +3922,7 @@  static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
                                          abi_long arg3,
                                          abi_long arg4)
 {
+#if TARGET_ABI_BITS == 32
 #ifdef TARGET_ARM
     if (((CPUARMState *)cpu_env)->eabi)
       {
@@ -3929,6 +3930,11 @@  static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
         arg3 = arg4;
       }
 #endif
+#if defined TARGET_PPC || defined TARGET_MIPS
+    arg2 = arg3;
+    arg3 = arg4;
+#endif
+#endif
     return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
 }
 #endif
@@ -3939,6 +3945,7 @@  static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
                                           abi_long arg3,
                                           abi_long arg4)
 {
+#if TARGET_ABI_BITS == 32
 #ifdef TARGET_ARM
     if (((CPUARMState *)cpu_env)->eabi)
       {
@@ -3946,10 +3953,63 @@  static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
         arg3 = arg4;
       }
 #endif
+#if defined TARGET_PPC || defined TARGET_MIPS
+    arg2 = arg3;
+    arg3 = arg4;
+#endif
+#endif
     return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
 }
 #endif
 
+#ifdef TARGET_NR_pread64
+static inline abi_long target_pread64(void *cpu_env, abi_long arg1,
+                                      void *arg2,
+                                      abi_long arg3,
+                                      abi_long arg4,
+                                      abi_long arg5,
+                                      abi_long arg6)
+{
+#if TARGET_ABI_BITS == 32
+#ifdef TARGET_ARM
+    if (((CPUARMState *)cpu_env)->eabi)
+      {
+        arg4 = arg5;
+        arg5 = arg6;
+      }
+#endif
+#if defined TARGET_PPC || defined TARGET_MIPS
+    arg4 = arg5;
+    arg5 = arg6;
+#endif
+#endif
+    return get_errno(pread64(arg1, arg2, arg3, target_offset64(arg4, arg5)));
+}
+
+static inline abi_long target_pwrite64(void *cpu_env, abi_long arg1,
+                                       const void *arg2,
+                                       abi_long arg3,
+                                       abi_long arg4,
+                                       abi_long arg5,
+                                       abi_long arg6)
+{
+#if TARGET_ABI_BITS == 32
+#ifdef TARGET_ARM
+    if (((CPUARMState *)cpu_env)->eabi)
+      {
+        arg4 = arg5;
+        arg5 = arg6;
+      }
+#endif
+#if defined TARGET_PPC || defined TARGET_MIPS
+    arg4 = arg5;
+    arg5 = arg6;
+#endif
+#endif
+    return get_errno(pwrite64(arg1, arg2, arg3, target_offset64(arg4, arg5)));
+}
+#endif
+
 static inline abi_long target_to_host_timespec(struct timespec *host_ts,
                                                abi_ulong target_addr)
 {
@@ -6166,13 +6226,13 @@  abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
     case TARGET_NR_pread64:
         if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
             goto efault;
-        ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
+        ret = target_pread64(cpu_env, arg1, p, arg3, arg4, arg5, arg6);
         unlock_user(p, arg2, ret);
         break;
     case TARGET_NR_pwrite64:
         if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
             goto efault;
-        ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
+        ret = target_pwrite64(cpu_env, arg1, p, arg3, arg4, arg5, arg6);
         unlock_user(p, arg2, 0);
         break;
 #endif