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
This commit is contained in:
David 'Digit' Turner 2010-12-16 16:47:14 +01:00
parent 4a7f31fad7
commit 95d751feac
23 changed files with 181 additions and 116 deletions

View File

@ -39,12 +39,10 @@ libc_common_src_files := \
unistd/perror.c \
unistd/popen.c \
unistd/pread.c \
unistd/pread64.c \
unistd/pselect.c \
unistd/ptsname.c \
unistd/ptsname_r.c \
unistd/pwrite.c \
unistd/pwrite64.c \
unistd/raise.c \
unistd/reboot.c \
unistd/recv.c \

View File

@ -85,8 +85,8 @@ int acct(const char* filepath) 51
# file descriptors
ssize_t read (int, void*, size_t) 3
ssize_t write (int, const void*, size_t) 4
ssize_t __pread64:pread64 (int, void *, size_t, off_t, off_t) 180
ssize_t __pwrite64:pwrite64 (int, void *, size_t, off_t, off_t) 181
ssize_t pread64 (int, void *, size_t, off64_t) 180
ssize_t pwrite64 (int, void *, size_t, off64_t) 181
int __open:open (const char*, int, mode_t) 5
int __openat:openat (int, const char*, int, mode_t) 322,295
int close (int) 6
@ -116,6 +116,7 @@ int pipe2(int *, int) 359,331
int dup2(int, int) 63
int select:_newselect(int, struct fd_set *, struct fd_set *, struct fd_set *, struct timeval *) 142
int ftruncate(int, off_t) 93
int ftruncate64(int, off64_t) 194
int getdents:getdents64(unsigned int, struct dirent *, unsigned int) 217,220
int fsync(int) 118
int fdatasync(int) 148

View File

@ -41,8 +41,8 @@ syscall_src += arch-arm/syscalls/sigaltstack.S
syscall_src += arch-arm/syscalls/acct.S
syscall_src += arch-arm/syscalls/read.S
syscall_src += arch-arm/syscalls/write.S
syscall_src += arch-arm/syscalls/__pread64.S
syscall_src += arch-arm/syscalls/__pwrite64.S
syscall_src += arch-arm/syscalls/pread64.S
syscall_src += arch-arm/syscalls/pwrite64.S
syscall_src += arch-arm/syscalls/__open.S
syscall_src += arch-arm/syscalls/__openat.S
syscall_src += arch-arm/syscalls/close.S
@ -70,6 +70,7 @@ syscall_src += arch-arm/syscalls/pipe2.S
syscall_src += arch-arm/syscalls/dup2.S
syscall_src += arch-arm/syscalls/select.S
syscall_src += arch-arm/syscalls/ftruncate.S
syscall_src += arch-arm/syscalls/ftruncate64.S
syscall_src += arch-arm/syscalls/getdents.S
syscall_src += arch-arm/syscalls/fsync.S
syscall_src += arch-arm/syscalls/fdatasync.S

View File

@ -0,0 +1,19 @@
/* autogenerated by gensyscalls.py */
#include <sys/linux-syscalls.h>
.text
.type ftruncate64, #function
.globl ftruncate64
.align 4
.fnstart
ftruncate64:
.save {r4, r7}
stmfd sp!, {r4, r7}
ldr r7, =__NR_ftruncate64
swi #0
ldmfd sp!, {r4, r7}
movs r0, r0
bxpl lr
b __set_syscall_errno
.fnend

View File

@ -2,12 +2,12 @@
#include <sys/linux-syscalls.h>
.text
.type __pread64, #function
.globl __pread64
.type pread64, #function
.globl pread64
.align 4
.fnstart
__pread64:
pread64:
mov ip, sp
.save {r4, r5, r6, r7}
stmfd sp!, {r4, r5, r6, r7}

View File

@ -2,12 +2,12 @@
#include <sys/linux-syscalls.h>
.text
.type __pwrite64, #function
.globl __pwrite64
.type pwrite64, #function
.globl pwrite64
.align 4
.fnstart
__pwrite64:
pwrite64:
mov ip, sp
.save {r4, r5, r6, r7}
stmfd sp!, {r4, r5, r6, r7}

View File

@ -45,8 +45,8 @@ syscall_src += arch-sh/syscalls/sigaltstack.S
syscall_src += arch-sh/syscalls/acct.S
syscall_src += arch-sh/syscalls/read.S
syscall_src += arch-sh/syscalls/write.S
syscall_src += arch-sh/syscalls/__pread64.S
syscall_src += arch-sh/syscalls/__pwrite64.S
syscall_src += arch-sh/syscalls/pread64.S
syscall_src += arch-sh/syscalls/pwrite64.S
syscall_src += arch-sh/syscalls/__open.S
syscall_src += arch-sh/syscalls/__openat.S
syscall_src += arch-sh/syscalls/close.S
@ -73,6 +73,7 @@ syscall_src += arch-sh/syscalls/pipe2.S
syscall_src += arch-sh/syscalls/dup2.S
syscall_src += arch-sh/syscalls/select.S
syscall_src += arch-sh/syscalls/ftruncate.S
syscall_src += arch-sh/syscalls/ftruncate64.S
syscall_src += arch-sh/syscalls/getdents.S
syscall_src += arch-sh/syscalls/fsync.S
syscall_src += arch-sh/syscalls/fdatasync.S

View File

@ -0,0 +1,32 @@
/* autogenerated by gensyscalls.py */
#include <sys/linux-syscalls.h>
.text
.type ftruncate64, @function
.globl ftruncate64
.align 4
ftruncate64:
/* invoke trap */
mov.l 0f, r3 /* trap num */
trapa #(3 + 0x10)
/* check return value */
cmp/pz r0
bt __NR_ftruncate64_end
/* keep error number */
sts.l pr, @-r15
mov.l 1f, r1
jsr @r1
mov r0, r4
lds.l @r15+, pr
__NR_ftruncate64_end:
rts
nop
.align 2
0: .long __NR_ftruncate64
1: .long __set_syscall_errno

View File

@ -2,11 +2,11 @@
#include <sys/linux-syscalls.h>
.text
.type __pread64, @function
.globl __pread64
.type pread64, @function
.globl pread64
.align 4
__pread64:
pread64:
/* get ready for additonal arg */
mov.l @r15, r0

View File

@ -2,11 +2,11 @@
#include <sys/linux-syscalls.h>
.text
.type __pwrite64, @function
.globl __pwrite64
.type pwrite64, @function
.globl pwrite64
.align 4
__pwrite64:
pwrite64:
/* get ready for additonal arg */
mov.l @r15, r0

View File

@ -44,8 +44,8 @@ syscall_src += arch-x86/syscalls/sigaltstack.S
syscall_src += arch-x86/syscalls/acct.S
syscall_src += arch-x86/syscalls/read.S
syscall_src += arch-x86/syscalls/write.S
syscall_src += arch-x86/syscalls/__pread64.S
syscall_src += arch-x86/syscalls/__pwrite64.S
syscall_src += arch-x86/syscalls/pread64.S
syscall_src += arch-x86/syscalls/pwrite64.S
syscall_src += arch-x86/syscalls/__open.S
syscall_src += arch-x86/syscalls/__openat.S
syscall_src += arch-x86/syscalls/close.S
@ -73,6 +73,7 @@ syscall_src += arch-x86/syscalls/pipe2.S
syscall_src += arch-x86/syscalls/dup2.S
syscall_src += arch-x86/syscalls/select.S
syscall_src += arch-x86/syscalls/ftruncate.S
syscall_src += arch-x86/syscalls/ftruncate64.S
syscall_src += arch-x86/syscalls/getdents.S
syscall_src += arch-x86/syscalls/fsync.S
syscall_src += arch-x86/syscalls/fdatasync.S

View File

@ -0,0 +1,29 @@
/* autogenerated by gensyscalls.py */
#include <sys/linux-syscalls.h>
.text
.type ftruncate64, @function
.globl ftruncate64
.align 4
ftruncate64:
pushl %ebx
pushl %ecx
pushl %edx
mov 16(%esp), %ebx
mov 20(%esp), %ecx
mov 24(%esp), %edx
movl $__NR_ftruncate64, %eax
int $0x80
cmpl $-129, %eax
jb 1f
negl %eax
pushl %eax
call __set_errno
addl $4, %esp
orl $-1, %eax
1:
popl %edx
popl %ecx
popl %ebx
ret

View File

@ -2,11 +2,11 @@
#include <sys/linux-syscalls.h>
.text
.type __pread64, @function
.globl __pread64
.type pread64, @function
.globl pread64
.align 4
__pread64:
pread64:
pushl %ebx
pushl %ecx
pushl %edx

View File

@ -2,11 +2,11 @@
#include <sys/linux-syscalls.h>
.text
.type __pwrite64, @function
.globl __pwrite64
.type pwrite64, @function
.globl pwrite64
.align 4
__pwrite64:
pwrite64:
pushl %ebx
pushl %ecx
pushl %edx

View File

@ -14,6 +14,8 @@ Differences between current and Android 2.3:
- <sched.h>: Add sched_getcpu(), sched_getaffinity(), sched_setaffinity(),
cpu_set_t and related macros (e.g. CPU_SETSIZE, CPU_ZERO, CPU_SET, ...)
- <unistd.h>: Add ftruncate64().
-------------------------------------------------------------------------------
Differences between Android 2.3 and Android 2.2:

View File

@ -71,6 +71,7 @@
#define __NR_dup2 (__NR_SYSCALL_BASE + 63)
#define __NR__newselect (__NR_SYSCALL_BASE + 142)
#define __NR_ftruncate (__NR_SYSCALL_BASE + 93)
#define __NR_ftruncate64 (__NR_SYSCALL_BASE + 194)
#define __NR_fsync (__NR_SYSCALL_BASE + 118)
#define __NR_fdatasync (__NR_SYSCALL_BASE + 148)
#define __NR_fchown32 (__NR_SYSCALL_BASE + 207)

View File

@ -52,8 +52,8 @@ int sigaltstack (const stack_t*, stack_t*);
int acct (const char* filepath);
ssize_t read (int, void*, size_t);
ssize_t write (int, const void*, size_t);
ssize_t __pread64 (int, void *, size_t, off_t, off_t);
ssize_t __pwrite64 (int, void *, size_t, off_t, off_t);
ssize_t pread64 (int, void *, size_t, off64_t);
ssize_t pwrite64 (int, void *, size_t, off64_t);
int __open (const char*, int, mode_t);
int __openat (int, const char*, int, mode_t);
int close (int);
@ -83,6 +83,7 @@ int pipe2 (int *, int);
int dup2 (int, int);
int select (int, struct fd_set *, struct fd_set *, struct fd_set *, struct timeval *);
int ftruncate (int, off_t);
int ftruncate64 (int, off64_t);
int getdents (unsigned int, struct dirent *, unsigned int);
int fsync (int);
int fdatasync (int);

View File

@ -145,6 +145,7 @@ extern int flock(int, int);
extern int fsync(int);
extern int fdatasync(int);
extern int ftruncate(int, off_t);
extern int ftruncate64(int, off64_t);
extern int pause(void);
extern unsigned int alarm(unsigned int);

View File

@ -245,6 +245,59 @@ superh_7args_header = """
"""
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 @@ class State:
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)

View File

@ -28,10 +28,8 @@
#include <sys/types.h>
#include <unistd.h>
extern int __pread64(int fd, void *buf, size_t nbytes, loff_t offset);
ssize_t pread(int fd, void *buf, size_t nbytes, off_t offset)
{
return __pread64(fd, buf, nbytes, offset);
return pread64(fd, buf, nbytes, (off64_t)offset);
}

View File

@ -1,37 +0,0 @@
/*
* Copyright (C) 2010 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/types.h>
#include <unistd.h>
extern int __pread64(int fd, void *buf, size_t nbytes, loff_t offset);
ssize_t pread64(int fd, void *buf, size_t nbytes, off64_t offset)
{
return __pread64(fd, buf, nbytes, offset);
}

View File

@ -28,10 +28,8 @@
#include <sys/types.h>
#include <unistd.h>
extern int __pwrite64(int fd, const void *buf, size_t nbytes, loff_t offset);
ssize_t pwrite(int fd, const void *buf, size_t nbytes, off_t offset)
{
return __pwrite64(fd, buf, nbytes, offset);
return pwrite64(fd, buf, nbytes, (off64_t)offset);
}

View File

@ -1,37 +0,0 @@
/*
* Copyright (C) 2010 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/types.h>
#include <unistd.h>
extern int __pwrite64(int fd, const void *buf, size_t nbytes, loff_t offset);
ssize_t pwrite64(int fd, const void *buf, size_t nbytes, off64_t offset)
{
return __pwrite64(fd, buf, nbytes, offset);
}