libc: Add ftruncate64 and improve 64-bit parameter syscall handling.

This patch improves the handling of 64-bit parameters in syscalls on ARM.
The ARM EABI mandates that 64-bit quantities be passed in even/odd register
pairs, which requires special treatment.

This allows us to simplify our implementations of pread() and pwrite()
and remove the C stubs for pread64() and pwrite64().

Also add ftruncate64() to <unistd.h>

Change-Id: I407e2fd223ba0093dd2d0b04c6152fadfc9ce3ef

Bug 3107933
diff --git a/libc/tools/gensyscalls.py b/libc/tools/gensyscalls.py
index 41c9500..0535e56 100755
--- a/libc/tools/gensyscalls.py
+++ b/libc/tools/gensyscalls.py
@@ -245,6 +245,59 @@
 """
 
 
+def param_uses_64bits(param):
+    """Returns True iff a syscall parameter description corresponds
+       to a 64-bit type."""
+    param = param.strip()
+    # First, check that the param type begins with one of the known
+    # 64-bit types.
+    if not ( \
+       param.startswith("int64_t") or param.startswith("uint64_t") or \
+       param.startswith("loff_t") or param.startswith("off64_t") or \
+       param.startswith("long long") or param.startswith("unsigned long long") or
+       param.startswith("signed long long") ):
+           return False
+
+    # Second, check that there is no pointer type here
+    if param.find("*") >= 0:
+            return False
+
+    # Ok
+    return True
+
+def count_arm_param_registers(params):
+    """This function is used to count the number of register used
+       to pass parameters when invoking a thumb or ARM system call.
+       This is because the ARM EABI mandates that 64-bit quantities
+       must be passed in an even+odd register pair. So, for example,
+       something like:
+
+             foo(int fd, off64_t pos)
+
+       would actually need 4 registers:
+             r0 -> int
+             r1 -> unused
+             r2-r3 -> pos
+   """
+    count = 0
+    for param in params:
+        if param_uses_64bits(param):
+            if (count & 1) != 0:
+                count += 1
+            count += 2
+        else:
+            count += 1
+    return count
+
+def count_generic_param_registers(params):
+    count = 0
+    for param in params:
+        if param_uses_64bits(param):
+            count += 2
+        else:
+            count += 1
+    return count
+
 class State:
     def __init__(self):
         self.old_stubs = []
@@ -370,25 +423,28 @@
             syscall_name   = t["name"]
 
             if t["id"] >= 0:
+                num_regs = count_arm_param_registers(syscall_params)
                 if gen_thumb_stubs:
-                    t["asm-thumb"] = self.thumb_genstub(syscall_func,len(syscall_params),"__NR_"+syscall_name)
+                    t["asm-thumb"] = self.thumb_genstub(syscall_func,num_regs,"__NR_"+syscall_name)
                 else:
                     if gen_eabi_stubs:
-                        t["asm-arm"]   = self.arm_eabi_genstub(syscall_func,len(syscall_params),"__NR_"+syscall_name)
+                        t["asm-arm"]   = self.arm_eabi_genstub(syscall_func,num_regs,"__NR_"+syscall_name)
                     else:
-                        t["asm-arm"]   = self.arm_genstub(syscall_func,len(syscall_params),"__NR_"+syscall_name)
+                        t["asm-arm"]   = self.arm_genstub(syscall_func,num_regs,"__NR_"+syscall_name)
 
             if t["id2"] >= 0:
+                num_regs = count_generic_param_registers(syscall_params)
                 if t["cid"] >= 0:
-                    t["asm-x86"] = self.x86_genstub_cid(syscall_func, len(syscall_params), "__NR_"+syscall_name, t["cid"])
+                    t["asm-x86"] = self.x86_genstub_cid(syscall_func, num_regs, "__NR_"+syscall_name, t["cid"])
                 else:
-                    t["asm-x86"] = self.x86_genstub(syscall_func,len(syscall_params),"__NR_"+syscall_name)
+                    t["asm-x86"] = self.x86_genstub(syscall_func, num_regs, "__NR_"+syscall_name)
             elif t["cid"] >= 0:
                 E("cid for dispatch syscalls is only supported for x86 in "
                   "'%s'" % syscall_name)
                 return
             if t["id3"] >= 0:
-                t["asm-sh"] = self.superh_genstub(syscall_func,len(syscall_params),"__NR_"+syscall_name)
+                num_regs = count_generic_param_registers(syscall_params)
+                t["asm-sh"] = self.superh_genstub(syscall_func,num_regs,"__NR_"+syscall_name)