Merge "Update capability.h"
diff --git a/libc/Android.mk b/libc/Android.mk
index 2c1a3a6..273b73e 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -490,14 +490,11 @@
# Define some common cflags
# ========================================================
libc_common_cflags := \
- -DWITH_ERRLIST \
-DANDROID_CHANGES \
-D_LIBC=1 \
- -DFLOATING_POINT \
-DINET6 \
-I$(LOCAL_PATH)/private \
-DPOSIX_MISTAKE \
- -DLOG_ON_HEAP_ERROR \
-Wall -Wextra
ifeq ($(strip $(DEBUG_BIONIC_LIBC)),true)
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 88c980f..17b6141 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -1,326 +1,319 @@
-# This file is used to automatically generate bionic's the system calls stubs.
+# This file is used to automatically generate bionic's system call stubs.
#
-# Each non comment line has the following format:
+# Each non-blank, non-comment line has the following format:
#
-# return_type func_name[:syscall_name[:call_id]]([parameter_list]) (1|-1|"stub")
+# return_type func_name[:syscall_name[:call_id]]([parameter_list]) arch_list
#
-# Note that:
+# where:
+# arch_list ::= "all" | "custom" | arch+
+# arch ::= "arm" | "mips" | "x86"
+#
+# Note:
# - syscall_name corresponds to the name of the syscall, which may differ from
# the exported function name (example: the exit syscall is implemented by the _exit()
# function, which is not the same as the standard C exit() function which calls it)
-# The call_id parameter, given that func_name and syscall_name have
+#
+# - The call_id parameter, given that func_name and syscall_name have
# been provided, allows the user to specify dispatch style syscalls.
# For example, socket() syscall on i386 actually becomes:
# socketcall(__NR_socket, 1, *(rest of args on stack)).
#
-# - each parameter type is assumed to be stored on 32 bits, there is no plan to support
-# 64-bit architectures at the moment
+# - Each parameter type is assumed to be stored in 32 bits.
#
-# - the final field can be "1", meaning: generate a stub for each architecture,
-# taking the constants from the kernel header files.
-#
-# - the final field can be "stub" meaning: do not generate any stubs ---
-# in this case, a hand-written custom stub must be provided.
-# TODO: replace this with something like "custom" or "none", or remove
-# it entirely.
-#
-# - the final field can be a three-element list of 1s and -1 meaning:
-# this system call is only available on some of the architectures (1),
-# and no stub should be generated for those architectures marked with -1.
-# the order is arm,x86,mips.
-# TODO: replace this with something more readable like "-arm,-mips" (meaning x86 only).
+# - The arch list can be the word "custom" meaning "do not generate any stubs".
+# In this case, a hand-written custom stub must be provided.
#
# This file is processed by a python script named gensyscalls.py.
-#
# process management
-void _exit:exit_group (int) 1
-void _exit_thread:exit (int) 1
-pid_t __fork:fork (void) 1
-pid_t _waitpid:waitpid (pid_t, int*, int, struct rusage*) -1,1,1
-int __waitid:waitid(int, pid_t, struct siginfo_t*, int,void*) 1
-pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage) 1
+void _exit:exit_group(int) all
+void _exit_thread:exit(int) all
+pid_t __fork:fork(void) all
+pid_t _waitpid:waitpid(pid_t, int*, int, struct rusage*) mips,x86
+int __waitid:waitid(int, pid_t, struct siginfo_t*, int, void*) all
+pid_t wait4(pid_t pid, int* status, int options, struct rusage* rusage) all
# NOTE: this system call is never called directly, but we list it there
# to have __NR_clone properly defined.
-#
-pid_t __sys_clone:clone (int, void*, int*, void*, int*) 1
+pid_t __sys_clone:clone(int, void*, int*, void*, int*) all
-int execve (const char*, char* const*, char* const*) 1
+int execve(const char*, char* const*, char* const*) all
-int __setuid:setuid32 (uid_t) 1,1,-1
-int __setuid:setuid (uid_t) -1,-1,1
-uid_t getuid:getuid32 () 1,1,-1
-uid_t getuid:getuid () -1,-1,1
-gid_t getgid:getgid32 () 1,1,-1
-gid_t getgid:getgid () -1,-1,1
-uid_t geteuid:geteuid32 () 1,1,-1
-uid_t geteuid:geteuid () -1,-1,1
-gid_t getegid:getegid32 () 1,1,-1
-gid_t getegid:getegid () -1,-1,1
-uid_t getresuid:getresuid32 (uid_t *ruid, uid_t *euid, uid_t *suid) 1,1,-1
-uid_t getresuid:getresuid (uid_t *ruid, uid_t *euid, uid_t *suid) -1,-1,1
-gid_t getresgid:getresgid32 (gid_t *rgid, gid_t *egid, gid_t *sgid) 1,1,-1
-gid_t getresgid:getresgid (gid_t *rgid, gid_t *egid, gid_t *sgid) -1,-1,1
-pid_t gettid() 1
-ssize_t readahead(int, off64_t, size_t) 1
-int getgroups:getgroups32(int, gid_t *) 1,1,-1
-int getgroups:getgroups(int, gid_t *) -1,-1,1
-pid_t getpgid(pid_t) 1
-pid_t getppid() 1
-pid_t getsid(pid_t) 1
-pid_t setsid() 1
-int setgid:setgid32(gid_t) 1,1,-1
-int setgid:setgid(gid_t) -1,-1,1
-int seteuid:seteuid32(uid_t) stub
-int __setreuid:setreuid32(uid_t, uid_t) 1,1,-1
-int __setreuid:setreuid(uid_t, uid_t) -1,-1,1
-int __setresuid:setresuid32(uid_t, uid_t, uid_t) 1,1,-1
-int __setresuid:setresuid(uid_t, uid_t, uid_t) -1,-1,1
-int setresgid:setresgid32(gid_t, gid_t, gid_t) 1,1,-1
-int setresgid:setresgid(gid_t, gid_t, gid_t) -1,-1,1
-void* __brk:brk(void*) 1
-# see comments in arch-arm/bionic/kill.S to understand why we don't generate an ARM stub for kill/tkill
-int kill(pid_t, int) -1,1,1
-int tkill(pid_t tid, int sig) -1,1,1
-int tgkill(pid_t tgid, pid_t tid, int sig) -1,1,1
-int __ptrace:ptrace(int request, int pid, void* addr, void* data) 1
-int __set_thread_area:set_thread_area(void* user_desc) -1,1,1
-int __getpriority:getpriority(int, int) 1
-int setpriority(int, int, int) 1
-int setrlimit(int resource, const struct rlimit *rlp) 1
-int getrlimit:ugetrlimit(int resource, struct rlimit *rlp) 1,1,-1
-int getrlimit:getrlimit(int resource, struct rlimit *rlp) -1,-1,1
-int getrusage(int who, struct rusage* r_usage) 1
-int setgroups:setgroups32(int, const gid_t *) 1,1,-1
-int setgroups:setgroups(int, const gid_t *) -1,-1,1
-pid_t getpgrp(void) stub
-int setpgid(pid_t, pid_t) 1
-pid_t vfork(void) 1,-1,-1
-int setregid:setregid32(gid_t, gid_t) 1,1,-1
-int setregid:setregid(gid_t, gid_t) -1,-1,1
-int chroot(const char *) 1
-# IMPORTANT: Even though <sys/prctl.h> declares prctl(int,...), the syscall stub must take 6 arguments
+int __setuid:setuid32(uid_t) arm,x86
+int __setuid:setuid(uid_t) mips
+uid_t getuid:getuid32() arm,x86
+uid_t getuid:getuid() mips
+gid_t getgid:getgid32() arm,x86
+gid_t getgid:getgid() mips
+uid_t geteuid:geteuid32() arm,x86
+uid_t geteuid:geteuid() mips
+gid_t getegid:getegid32() arm,x86
+gid_t getegid:getegid() mips
+uid_t getresuid:getresuid32(uid_t* ruid, uid_t* euid, uid_t* suid) arm,x86
+uid_t getresuid:getresuid(uid_t* ruid, uid_t* euid, uid_t* suid) mips
+gid_t getresgid:getresgid32(gid_t* rgid, gid_t* egid, gid_t* sgid) arm,x86
+gid_t getresgid:getresgid(gid_t* rgid, gid_t* egid, gid_t* sgid) mips
+pid_t gettid() all
+ssize_t readahead(int, off64_t, size_t) all
+int getgroups:getgroups32(int, gid_t*) arm,x86
+int getgroups:getgroups(int, gid_t*) mips
+pid_t getpgid(pid_t) all
+pid_t getppid() all
+pid_t getsid(pid_t) all
+pid_t setsid() all
+int setgid:setgid32(gid_t) arm,x86
+int setgid:setgid(gid_t) mips
+int seteuid:seteuid32(uid_t) custom
+int __setreuid:setreuid32(uid_t, uid_t) arm,x86
+int __setreuid:setreuid(uid_t, uid_t) mips
+int __setresuid:setresuid32(uid_t, uid_t, uid_t) arm,x86
+int __setresuid:setresuid(uid_t, uid_t, uid_t) mips
+int setresgid:setresgid32(gid_t, gid_t, gid_t) arm,x86
+int setresgid:setresgid(gid_t, gid_t, gid_t) mips
+void* __brk:brk(void*) all
+# See comments in kill.S to understand why we don't generate ARM stubs for kill/tkill/tgkill.
+int kill(pid_t, int) mips,x86
+int tkill(pid_t tid, int sig) mips,x86
+int tgkill(pid_t tgid, pid_t tid, int sig) mips,x86
+int __ptrace:ptrace(int request, int pid, void* addr, void* data) all
+int __set_thread_area:set_thread_area(void* user_desc) mips,x86
+int __getpriority:getpriority(int, int) all
+int setpriority(int, int, int) all
+int setrlimit(int resource, const struct rlimit* rlp) all
+int getrlimit:ugetrlimit(int resource, struct rlimit* rlp) arm,x86
+int getrlimit:getrlimit(int resource, struct rlimit* rlp) mips
+int getrusage(int who, struct rusage* r_usage) all
+int setgroups:setgroups32(int, const gid_t*) arm,x86
+int setgroups:setgroups(int, const gid_t*) mips
+pid_t getpgrp(void) custom
+int setpgid(pid_t, pid_t) all
+pid_t vfork(void) arm
+int setregid:setregid32(gid_t, gid_t) arm,x86
+int setregid:setregid(gid_t, gid_t) mips
+int chroot(const char*) all
+# IMPORTANT: Even though <sys/prctl.h> declares prctl(int, ...), the syscall stub must take 6 arguments
# to match the kernel implementation.
-int prctl(int option, unsigned int arg2, unsigned int arg3, unsigned int arg4, unsigned int arg5) 1
-int capget(cap_user_header_t header, cap_user_data_t data) 1
-int capset(cap_user_header_t header, const cap_user_data_t data) 1
-int sigaltstack(const stack_t*, stack_t*) 1
-int acct(const char* filepath) 1
+int prctl(int option, unsigned int arg2, unsigned int arg3, unsigned int arg4, unsigned int arg5) all
+int capget(cap_user_header_t header, cap_user_data_t data) all
+int capset(cap_user_header_t header, const cap_user_data_t data) all
+int sigaltstack(const stack_t*, stack_t*) all
+int acct(const char* filepath) all
# file descriptors
-ssize_t read (int, void*, size_t) 1
-ssize_t write (int, const void*, size_t) 1
-ssize_t pread64 (int, void *, size_t, off64_t) 1
-ssize_t pwrite64 (int, void *, size_t, off64_t) 1
-int __open:open (const char*, int, mode_t) 1
-int __openat:openat (int, const char*, int, mode_t) 1
-int close (int) 1
-int creat(const char*, mode_t) stub
-off_t lseek(int, off_t, int) 1
-int __llseek:_llseek (int, unsigned long, unsigned long, loff_t*, int) 1
-pid_t getpid () 1
-void * mmap(void *, size_t, int, int, int, long) stub
-void * __mmap2:mmap2(void*, size_t, int, int, int, long) 1
-int munmap(void *, size_t) 1
-void * mremap(void *, size_t, size_t, unsigned long) 1
-int msync(const void *, size_t, int) 1
-int mprotect(const void *, size_t, int) 1
-int madvise(const void *, size_t, int) 1
-int mlock(const void *addr, size_t len) 1
-int munlock(const void *addr, size_t len) 1
-int mlockall(int flags) 1
-int munlockall() 1
-int mincore(void* start, size_t length, unsigned char* vec) 1
-int __ioctl:ioctl(int, int, void *) 1
-int readv(int, const struct iovec *, int) 1
-int writev(int, const struct iovec *, int) 1
-int __fcntl:fcntl(int, int, void*) 1
-int flock(int, int) 1
-int fchmod(int, mode_t) 1
-int dup(int) 1
-int pipe(int *) 1,1,-1
-int pipe2(int *, int) 1
-int dup2(int, int) 1
-int select:_newselect(int, struct fd_set *, struct fd_set *, struct fd_set *, struct timeval *) 1
-int ftruncate(int, off_t) 1
-int ftruncate64(int, off64_t) 1
-int getdents:getdents64(unsigned int, struct dirent *, unsigned int) 1
-int fsync(int) 1
-int fdatasync(int) 1
-int fchown:fchown32(int, uid_t, gid_t) 1,1,-1
-int fchown:fchown(int, uid_t, gid_t) -1,-1,1
-void sync(void) 1
-int __fcntl64:fcntl64(int, int, void *) 1
-int __fstatfs64:fstatfs64(int, size_t, struct statfs *) 1
-ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count) 1
-int fstatat:fstatat64(int dirfd, const char *path, struct stat *buf, int flags) 1
-int mkdirat(int dirfd, const char *pathname, mode_t mode) 1
-int fchownat(int dirfd, const char *path, uid_t owner, gid_t group, int flags) 1
-int fchmodat(int dirfd, const char *path, mode_t mode, int flags) 1
-int renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) 1
-int fsetxattr(int, const char *, const void *, size_t, int) 1
-ssize_t fgetxattr(int, const char *, void *, size_t) 1
-ssize_t flistxattr(int, char *, size_t) 1
-int fremovexattr(int, const char *) 1
+ssize_t read(int, void*, size_t) all
+ssize_t write(int, const void*, size_t) all
+ssize_t pread64(int, void*, size_t, off64_t) all
+ssize_t pwrite64(int, void*, size_t, off64_t) all
+int __open:open(const char*, int, mode_t) all
+int __openat:openat(int, const char*, int, mode_t) all
+int close(int) all
+int creat(const char*, mode_t) custom
+off_t lseek(int, off_t, int) all
+int __llseek:_llseek(int, unsigned long, unsigned long, off64_t*, int) all
+pid_t getpid() all
+void* mmap(void*, size_t, int, int, int, long) custom
+void* __mmap2:mmap2(void*, size_t, int, int, int, long) all
+int munmap(void*, size_t) all
+void* mremap(void*, size_t, size_t, unsigned long) all
+int msync(const void*, size_t, int) all
+int mprotect(const void*, size_t, int) all
+int madvise(const void*, size_t, int) all
+int mlock(const void* addr, size_t len) all
+int munlock(const void* addr, size_t len) all
+int mlockall(int flags) all
+int munlockall() all
+int mincore(void* start, size_t length, unsigned char* vec) all
+int __ioctl:ioctl(int, int, void*) all
+int readv(int, const struct iovec*, int) all
+int writev(int, const struct iovec*, int) all
+int __fcntl:fcntl(int, int, void*) all
+int flock(int, int) all
+int fchmod(int, mode_t) all
+int dup(int) all
+int pipe(int*) arm,x86
+int pipe2(int*, int) all
+int dup2(int, int) all
+int select:_newselect(int, struct fd_set*, struct fd_set*, struct fd_set*, struct timeval*) all
+int ftruncate(int, off_t) all
+int ftruncate64(int, off64_t) all
+int getdents:getdents64(unsigned int, struct dirent*, unsigned int) all
+int fsync(int) all
+int fdatasync(int) all
+int fchown:fchown32(int, uid_t, gid_t) arm,x86
+int fchown:fchown(int, uid_t, gid_t) mips
+void sync(void) all
+int __fcntl64:fcntl64(int, int, void*) all
+int __fstatfs64:fstatfs64(int, size_t, struct statfs*) all
+ssize_t sendfile(int out_fd, int in_fd, off_t* offset, size_t count) all
+ssize_t sendfile64(int out_fd, int in_fd, off64_t* offset, size_t count) all
+int fstatat:fstatat64(int dirfd, const char* path, struct stat* buf, int flags) all
+int mkdirat(int dirfd, const char* pathname, mode_t mode) all
+int fchownat(int dirfd, const char* path, uid_t owner, gid_t group, int flags) all
+int fchmodat(int dirfd, const char* path, mode_t mode, int flags) all
+int renameat(int olddirfd, const char* oldpath, int newdirfd, const char* newpath) all
+int fsetxattr(int, const char*, const void*, size_t, int) all
+ssize_t fgetxattr(int, const char*, void*, size_t) all
+ssize_t flistxattr(int, char*, size_t) all
+int fremovexattr(int, const char*) all
# file system
-int link (const char*, const char*) 1
-int unlink (const char*) 1
-int unlinkat (int, const char *, int) 1
-int chdir (const char*) 1
-int mknod (const char*, mode_t, dev_t) 1
-int chmod (const char*,mode_t) 1
-int chown:chown32(const char *, uid_t, gid_t) 1,1,-1
-int chown:chown(const char *, uid_t, gid_t) -1,-1,1
-int lchown:lchown32 (const char*, uid_t, gid_t) 1,1,-1
-int lchown:lchown (const char*, uid_t, gid_t) -1,-1,1
-int mount (const char*, const char*, const char*, unsigned long, const void*) 1
-int umount(const char*) stub
-int umount2 (const char*, int) 1
-int fstat:fstat64(int, struct stat*) 1
-int stat:stat64(const char *, struct stat *) 1
-int lstat:lstat64(const char *, struct stat *) 1
-int mkdir(const char *, mode_t) 1
-int readlink(const char *, char *, size_t) 1
-int rmdir(const char *) 1
-int rename(const char *, const char *) 1
-int __getcwd:getcwd(char * buf, size_t size) 1
-int access(const char *, int) 1
-int faccessat(int, const char *, int, int) 1
-int symlink(const char *, const char *) 1
-int fchdir(int) 1
-int truncate(const char*, off_t) 1
-int setxattr(const char *, const char *, const void *, size_t, int) 1
-int lsetxattr(const char *, const char *, const void *, size_t, int) 1
-ssize_t getxattr(const char *, const char *, void *, size_t) 1
-ssize_t lgetxattr(const char *, const char *, void *, size_t) 1
-ssize_t listxattr(const char *, char *, size_t) 1
-ssize_t llistxattr(const char *, char *, size_t) 1
-int removexattr(const char *, const char *) 1
-int lremovexattr(const char *, const char *) 1
-int __statfs64:statfs64(const char *, size_t, struct statfs *) 1
-long unshare(unsigned long) 1
-int swapon(const char *, int) 1
-int swapoff(const char *) 1
+int link(const char*, const char*) all
+int unlink(const char*) all
+int unlinkat(int, const char*, int) all
+int chdir(const char*) all
+int mknod(const char*, mode_t, dev_t) all
+int chmod(const char*, mode_t) all
+int chown:chown32(const char*, uid_t, gid_t) arm,x86
+int chown:chown(const char*, uid_t, gid_t) mips
+int lchown:lchown32(const char*, uid_t, gid_t) arm,x86
+int lchown:lchown(const char*, uid_t, gid_t) mips
+int mount(const char*, const char*, const char*, unsigned long, const void*) all
+int umount(const char*) custom
+int umount2(const char*, int) all
+int fstat:fstat64(int, struct stat*) all
+int stat:stat64(const char*, struct stat*) all
+int lstat:lstat64(const char*, struct stat*) all
+int mkdir(const char*, mode_t) all
+int readlink(const char*, char*, size_t) all
+int rmdir(const char*) all
+int rename(const char*, const char*) all
+int __getcwd:getcwd(char* buf, size_t size) all
+int access(const char*, int) all
+int faccessat(int, const char*, int, int) all
+int symlink(const char*, const char*) all
+int fchdir(int) all
+int truncate(const char*, off_t) all
+int truncate64(const char*, off64_t) all
+int setxattr(const char*, const char*, const void*, size_t, int) all
+int lsetxattr(const char*, const char*, const void*, size_t, int) all
+ssize_t getxattr(const char*, const char*, void*, size_t) all
+ssize_t lgetxattr(const char*, const char*, void*, size_t) all
+ssize_t listxattr(const char*, char*, size_t) all
+ssize_t llistxattr(const char*, char*, size_t) all
+int removexattr(const char*, const char*) all
+int lremovexattr(const char*, const char*) all
+int __statfs64:statfs64(const char*, size_t, struct statfs*) all
+long unshare(unsigned long) all
+int swapon(const char*, int) all
+int swapoff(const char*) all
# time
-int pause () 1
-int gettimeofday(struct timeval*, struct timezone*) 1
-int settimeofday(const struct timeval*, const struct timezone*) 1
-clock_t times(struct tms *) 1
-int nanosleep(const struct timespec *, struct timespec *) 1
-int clock_gettime(clockid_t clk_id, struct timespec *tp) 1
-int clock_settime(clockid_t clk_id, const struct timespec *tp) 1
-int clock_getres(clockid_t clk_id, struct timespec *res) 1
-int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *req, struct timespec *rem) 1
-int getitimer(int, const struct itimerval *) 1
-int setitimer(int, const struct itimerval *, struct itimerval *) 1
-int __timer_create:timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid) 1
-int __timer_settime:timer_settime(timer_t, int, const struct itimerspec*, struct itimerspec*) 1
-int __timer_gettime:timer_gettime(timer_t, struct itimerspec*) 1
-int __timer_getoverrun:timer_getoverrun(timer_t) 1
-int __timer_delete:timer_delete(timer_t) 1
-int utimes(const char*, const struct timeval tvp[2]) 1
-int utimensat(int, const char *, const struct timespec times[2], int) 1
-int timerfd_create(clockid_t, int) 1
-int timerfd_settime(int, int, const struct itimerspec *, struct itimerspec *) 1
-int timerfd_gettime(int, struct itimerspec *) 1
+int pause() all
+int gettimeofday(struct timeval*, struct timezone*) all
+int settimeofday(const struct timeval*, const struct timezone*) all
+clock_t times(struct tms*) all
+int nanosleep(const struct timespec*, struct timespec*) all
+int clock_gettime(clockid_t clk_id, struct timespec* tp) all
+int clock_settime(clockid_t clk_id, const struct timespec* tp) all
+int clock_getres(clockid_t clk_id, struct timespec* res) all
+int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec* req, struct timespec* rem) all
+int getitimer(int, const struct itimerval*) all
+int setitimer(int, const struct itimerval*, struct itimerval*) all
+int __timer_create:timer_create(clockid_t clockid, struct sigevent* evp, timer_t* timerid) all
+int __timer_settime:timer_settime(timer_t, int, const struct itimerspec*, struct itimerspec*) all
+int __timer_gettime:timer_gettime(timer_t, struct itimerspec*) all
+int __timer_getoverrun:timer_getoverrun(timer_t) all
+int __timer_delete:timer_delete(timer_t) all
+int utimes(const char*, const struct timeval tvp[2]) all
+int utimensat(int, const char*, const struct timespec times[2], int) all
+int timerfd_create(clockid_t, int) all
+int timerfd_settime(int, int, const struct itimerspec*, struct itimerspec*) all
+int timerfd_gettime(int, struct itimerspec*) all
# signals
-int sigaction(int, const struct sigaction *, struct sigaction *) 1
-int sigprocmask(int, const sigset_t *, sigset_t *) 1
-int __sigsuspend:sigsuspend(int unused1, int unused2, unsigned mask) 1,1,-1
-int __sigsuspend:sigsuspend(const sigset_t *mask) -1,-1,1
-int __rt_sigaction:rt_sigaction (int sig, const struct sigaction *act, struct sigaction *oact, size_t sigsetsize) 1
-int __rt_sigprocmask:rt_sigprocmask (int how, const sigset_t *set, sigset_t *oset, size_t sigsetsize) 1
-int __rt_sigtimedwait:rt_sigtimedwait(const sigset_t *set, struct siginfo_t *info, struct timespec_t *timeout, size_t sigset_size) 1
-int sigpending(sigset_t *) 1
-int signalfd4(int fd, const sigset_t *mask, size_t sizemask, int flags) 1
+int sigaction(int, const struct sigaction*, struct sigaction*) all
+int sigprocmask(int, const sigset_t*, sigset_t*) all
+int __sigsuspend:sigsuspend(int unused1, int unused2, unsigned mask) arm,x86
+int __sigsuspend:sigsuspend(const sigset_t* mask) mips
+int __rt_sigaction:rt_sigaction(int sig, const struct sigaction* act, struct sigaction* oact, size_t sigsetsize) all
+int __rt_sigprocmask:rt_sigprocmask(int how, const sigset_t* set, sigset_t* oset, size_t sigsetsize) all
+int __rt_sigtimedwait:rt_sigtimedwait(const sigset_t* set, struct siginfo_t* info, struct timespec_t* timeout, size_t sigset_size) all
+int sigpending(sigset_t*) all
+int signalfd4(int fd, const sigset_t* mask, size_t sizemask, int flags) all
# sockets
-int socket(int, int, int) 1,-1,1
-int socketpair(int, int, int, int*) 1,-1,1
-int bind(int, struct sockaddr *, int) 1,-1,1
-int connect(int, struct sockaddr *, socklen_t) 1,-1,1
-int listen(int, int) 1,-1,1
-int accept(int, struct sockaddr *, socklen_t *) 1,-1,1
-int getsockname(int, struct sockaddr *, socklen_t *) 1,-1,1
-int getpeername(int, struct sockaddr *, socklen_t *) 1,-1,1
-int sendto(int, const void *, size_t, int, const struct sockaddr *, socklen_t) 1,-1,1
-int recvfrom(int, void *, size_t, unsigned int, struct sockaddr *, socklen_t *) 1,-1,1
-int shutdown(int, int) 1,-1,1
-int setsockopt(int, int, int, const void *, socklen_t) 1,-1,1
-int getsockopt(int, int, int, void *, socklen_t *) 1,-1,1
-int sendmsg(int, const struct msghdr *, unsigned int) 1,-1,1
-int recvmsg(int, struct msghdr *, unsigned int) 1,-1,1
+int socket(int, int, int) arm,mips
+int socketpair(int, int, int, int*) arm,mips
+int bind(int, struct sockaddr*, int) arm,mips
+int connect(int, struct sockaddr*, socklen_t) arm,mips
+int listen(int, int) arm,mips
+int accept(int, struct sockaddr*, socklen_t*) arm,mips
+int getsockname(int, struct sockaddr*, socklen_t*) arm,mips
+int getpeername(int, struct sockaddr*, socklen_t*) arm,mips
+int sendto(int, const void*, size_t, int, const struct sockaddr*, socklen_t) arm,mips
+int recvfrom(int, void*, size_t, unsigned int, struct sockaddr*, socklen_t*) arm,mips
+int shutdown(int, int) arm,mips
+int setsockopt(int, int, int, const void*, socklen_t) arm,mips
+int getsockopt(int, int, int, void*, socklen_t*) arm,mips
+int sendmsg(int, const struct msghdr*, unsigned int) arm,mips
+int recvmsg(int, struct msghdr*, unsigned int) arm,mips
# sockets for x86. These are done as an "indexed" call to socketcall syscall.
-int socket:socketcall:1 (int, int, int) -1,1,-1
-int bind:socketcall:2 (int, struct sockaddr *, int) -1,1,-1
-int connect:socketcall:3(int, struct sockaddr *, socklen_t) -1,1,-1
-int listen:socketcall:4(int, int) -1,1,-1
-int accept:socketcall:5(int, struct sockaddr *, socklen_t *) -1,1,-1
-int getsockname:socketcall:6(int, struct sockaddr *, socklen_t *) -1,1,-1
-int getpeername:socketcall:7(int, struct sockaddr *, socklen_t *) -1,1,-1
-int socketpair:socketcall:8(int, int, int, int*) -1,1,-1
-int sendto:socketcall:11(int, const void *, size_t, int, const struct sockaddr *, socklen_t) -1,1,-1
-int recvfrom:socketcall:12(int, void *, size_t, unsigned int, struct sockaddr *, socklen_t *) -1,1,-1
-int shutdown:socketcall:13(int, int) -1,1,-1
-int setsockopt:socketcall:14(int, int, int, const void *, socklen_t) -1,1,-1
-int getsockopt:socketcall:15(int, int, int, void *, socklen_t *) -1,1,-1
-int sendmsg:socketcall:16(int, const struct msghdr *, unsigned int) -1,1,-1
-int recvmsg:socketcall:17(int, struct msghdr *, unsigned int) -1,1,-1
+int socket:socketcall:1(int, int, int) x86
+int bind:socketcall:2(int, struct sockaddr*, int) x86
+int connect:socketcall:3(int, struct sockaddr*, socklen_t) x86
+int listen:socketcall:4(int, int) x86
+int accept:socketcall:5(int, struct sockaddr*, socklen_t*) x86
+int getsockname:socketcall:6(int, struct sockaddr*, socklen_t*) x86
+int getpeername:socketcall:7(int, struct sockaddr*, socklen_t*) x86
+int socketpair:socketcall:8(int, int, int, int*) x86
+int sendto:socketcall:11(int, const void*, size_t, int, const struct sockaddr*, socklen_t) x86
+int recvfrom:socketcall:12(int, void*, size_t, unsigned int, struct sockaddr*, socklen_t*) x86
+int shutdown:socketcall:13(int, int) x86
+int setsockopt:socketcall:14(int, int, int, const void*, socklen_t) x86
+int getsockopt:socketcall:15(int, int, int, void*, socklen_t*) x86
+int sendmsg:socketcall:16(int, const struct msghdr*, unsigned int) x86
+int recvmsg:socketcall:17(int, struct msghdr*, unsigned int) x86
# scheduler & real-time
-int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param) 1
-int sched_getscheduler(pid_t pid) 1
-int sched_yield(void) 1
-int sched_setparam(pid_t pid, const struct sched_param *param) 1
-int sched_getparam(pid_t pid, struct sched_param *param) 1
-int sched_get_priority_max(int policy) 1
-int sched_get_priority_min(int policy) 1
-int sched_rr_get_interval(pid_t pid, struct timespec *interval) 1
-int sched_setaffinity(pid_t pid, size_t setsize, const cpu_set_t* set) 1
-int __sched_getaffinity:sched_getaffinity(pid_t pid, size_t setsize, cpu_set_t* set) 1
-int __getcpu:getcpu(unsigned *cpu, unsigned *node, void *unused) 1
+int sched_setscheduler(pid_t pid, int policy, const struct sched_param* param) all
+int sched_getscheduler(pid_t pid) all
+int sched_yield(void) all
+int sched_setparam(pid_t pid, const struct sched_param* param) all
+int sched_getparam(pid_t pid, struct sched_param* param) all
+int sched_get_priority_max(int policy) all
+int sched_get_priority_min(int policy) all
+int sched_rr_get_interval(pid_t pid, struct timespec* interval) all
+int sched_setaffinity(pid_t pid, size_t setsize, const cpu_set_t* set) all
+int __sched_getaffinity:sched_getaffinity(pid_t pid, size_t setsize, cpu_set_t* set) all
+int __getcpu:getcpu(unsigned* cpu, unsigned* node, void* unused) all
# io priorities
-int ioprio_set(int which, int who, int ioprio) 1
-int ioprio_get(int which, int who) 1
+int ioprio_set(int which, int who, int ioprio) all
+int ioprio_get(int which, int who) all
# other
-int uname(struct utsname *) 1
-mode_t umask(mode_t) 1
-int __reboot:reboot(int, int, int, void *) 1
-int __syslog:syslog(int, char *, int) 1
-int init_module(void *, unsigned long, const char *) 1
-int delete_module(const char*, unsigned int) 1
-int klogctl:syslog(int, char *, int) 1
-int sysinfo(struct sysinfo *) 1
-int personality(unsigned long) 1
-long perf_event_open(struct perf_event_attr *attr_uptr, pid_t pid, int cpu, int group_fd, unsigned long flags) 1
+int uname(struct utsname*) all
+mode_t umask(mode_t) all
+int __reboot:reboot(int, int, int, void*) all
+int __syslog:syslog(int, char*, int) all
+int init_module(void*, unsigned long, const char*) all
+int delete_module(const char*, unsigned int) all
+int klogctl:syslog(int, char*, int) all
+int sysinfo(struct sysinfo*) all
+int personality(unsigned long) all
+long perf_event_open(struct perf_event_attr* attr_uptr, pid_t pid, int cpu, int group_fd, unsigned long flags) all
# futex
-int futex(void *, int, int, void *, void *, int) 1
+int futex(void*, int, int, void*, void*, int) all
# epoll
-int epoll_create(int size) 1
-int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) 1
-int epoll_wait(int epfd, struct epoll_event *events, int max, int timeout) 1
+int epoll_create(int size) all
+int epoll_ctl(int epfd, int op, int fd, struct epoll_event* event) all
+int epoll_wait(int epfd, struct epoll_event* events, int max, int timeout) all
-int inotify_init(void) 1
-int inotify_add_watch(int, const char *, unsigned int) 1
-int inotify_rm_watch(int, unsigned int) 1
+int inotify_init(void) all
+int inotify_add_watch(int, const char*, unsigned int) all
+int inotify_rm_watch(int, unsigned int) all
-int poll(struct pollfd *, unsigned int, long) 1
+int poll(struct pollfd*, unsigned int, long) all
-int eventfd:eventfd2(unsigned int, int) 1
+int eventfd:eventfd2(unsigned int, int) all
# ARM-specific ARM_NR_BASE == 0x0f0000 == 983040
-int __set_tls:__ARM_NR_set_tls(void*) 1,-1,-1
-int cacheflush:__ARM_NR_cacheflush(long start, long end, long flags) 1,-1,-1
+int __set_tls:__ARM_NR_set_tls(void*) arm
+int cacheflush:__ARM_NR_cacheflush(long start, long end, long flags) arm
# MIPS-specific
-int _flush_cache:cacheflush(char *addr, const int nbytes, const int op) -1,-1,1
-int syscall(int number,...) -1,-1,1
+int _flush_cache:cacheflush(char* addr, const int nbytes, const int op) mips
+int syscall(int number, ...) mips
diff --git a/libc/arch-arm/arm.mk b/libc/arch-arm/arm.mk
index e87ef38..5f2443f 100644
--- a/libc/arch-arm/arm.mk
+++ b/libc/arch-arm/arm.mk
@@ -21,10 +21,11 @@
# These are used by the static and dynamic versions of the libc
# respectively.
_LIBC_ARCH_STATIC_SRC_FILES := \
- arch-arm/bionic/exidx_static.c
+ arch-arm/bionic/exidx_static.c \
+ bionic/dl_iterate_phdr_static.c \
_LIBC_ARCH_DYNAMIC_SRC_FILES := \
- arch-arm/bionic/exidx_dynamic.c
+ arch-arm/bionic/exidx_dynamic.c \
# Remove the C++ fortify function implementations for which there is an
# arm assembler version.
diff --git a/libc/arch-arm/cortex-a15/bionic/__strcat_chk.S b/libc/arch-arm/cortex-a15/bionic/__strcat_chk.S
index 08dc78a..4aaa9f1 100644
--- a/libc/arch-arm/cortex-a15/bionic/__strcat_chk.S
+++ b/libc/arch-arm/cortex-a15/bionic/__strcat_chk.S
@@ -41,13 +41,15 @@
.cfi_startproc
pld [r0, #0]
push {r0, lr}
+ .save {r0, lr}
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
push {r4, r5}
+ .save {r4, r5}
.cfi_adjust_cfa_offset 8
.cfi_rel_offset r4, 0
- .cfi_rel_offset r5, 0
+ .cfi_rel_offset r5, 4
mov lr, r2
@@ -178,7 +180,7 @@
.L_strlen_done:
add r2, r3, r4
cmp r2, lr
- bgt .L_fortify_check_failed
+ bhi __strcat_chk_failed
// Set up the registers for the memcpy code.
mov r1, r5
@@ -186,13 +188,23 @@
mov r2, r4
add r0, r0, r3
pop {r4, r5}
- .cfi_adjust_cfa_offset -8
- .cfi_restore r4
- .cfi_restore r5
- #include "memcpy_base.S"
+ .cfi_endproc
+END(__strcat_chk)
-.L_fortify_check_failed:
+#define MEMCPY_BASE __strcat_chk_memcpy_base
+#define MEMCPY_BASE_ALIGNED __strcat_chk_memcpy_base_aligned
+
+#include "memcpy_base.S"
+
+ENTRY(__strcat_chk_failed)
+ .cfi_startproc
+ .save {r0, lr}
+ .save {r4, r5}
+
+ .cfi_def_cfa_offset 8
+ .cfi_rel_offset r0, 0
+ .cfi_rel_offset lr, 4
.cfi_adjust_cfa_offset 8
.cfi_rel_offset r4, 0
.cfi_rel_offset r5, 4
@@ -208,7 +220,7 @@
.word error_string-(1b+4)
.cfi_endproc
-END(__strcat_chk)
+END(__strcat_chk_failed)
.data
error_string:
diff --git a/libc/arch-arm/cortex-a15/bionic/__strcpy_chk.S b/libc/arch-arm/cortex-a15/bionic/__strcpy_chk.S
index 9fde590..05152e6 100644
--- a/libc/arch-arm/cortex-a15/bionic/__strcpy_chk.S
+++ b/libc/arch-arm/cortex-a15/bionic/__strcpy_chk.S
@@ -40,6 +40,7 @@
.cfi_startproc
pld [r0, #0]
push {r0, lr}
+ .save {r0, lr}
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
@@ -150,14 +151,25 @@
pld [r1, #64]
ldr r0, [sp]
cmp r3, lr
- bge .L_fortify_check_failed
+ bhs __strcpy_chk_failed
// Add 1 for copy length to get the string terminator.
add r2, r3, #1
- #include "memcpy_base.S"
+ .cfi_endproc
+END(__strcpy_chk)
-.L_fortify_check_failed:
+#define MEMCPY_BASE __strcpy_chk_memcpy_base
+#define MEMCPY_BASE_ALIGNED __strcpy_chk_memcpy_base_aligned
+#include "memcpy_base.S"
+
+ENTRY(__strcpy_chk_failed)
+ .cfi_startproc
+ .save {r0, lr}
+ .cfi_def_cfa_offset 8
+ .cfi_rel_offset r0, 0
+ .cfi_rel_offset lr, 4
+
ldr r0, error_message
ldr r1, error_code
1:
@@ -169,7 +181,7 @@
.word error_string-(1b+4)
.cfi_endproc
-END(__strcpy_chk)
+END(__strcpy_chk_failed)
.data
error_string:
diff --git a/libc/arch-arm/cortex-a15/bionic/memcpy.S b/libc/arch-arm/cortex-a15/bionic/memcpy.S
index 8052d62..a843230 100644
--- a/libc/arch-arm/cortex-a15/bionic/memcpy.S
+++ b/libc/arch-arm/cortex-a15/bionic/memcpy.S
@@ -65,7 +65,7 @@
ENTRY(__memcpy_chk)
.cfi_startproc
cmp r2, r3
- bgt __memcpy_chk_fail
+ bhi __memcpy_chk_fail
// Fall through to memcpy...
.cfi_endproc
@@ -75,18 +75,23 @@
.cfi_startproc
pld [r1, #64]
push {r0, lr}
+ .save {r0, lr}
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
- #include "memcpy_base.S"
.cfi_endproc
END(memcpy)
+#define MEMCPY_BASE __memcpy_base
+#define MEMCPY_BASE_ALIGNED __memcpy_base_aligned
+#include "memcpy_base.S"
+
+ENTRY(__memcpy_chk_fail)
.cfi_startproc
-__memcpy_chk_fail:
// Preserve lr for backtrace.
push {lr}
+ .save {lr}
.cfi_def_cfa_offset 4
.cfi_rel_offset lr, 0
@@ -100,6 +105,7 @@
error_message:
.word error_string-(1b+8)
.cfi_endproc
+END(__memcpy_chk_fail)
.data
error_string:
diff --git a/libc/arch-arm/cortex-a15/bionic/memcpy_base.S b/libc/arch-arm/cortex-a15/bionic/memcpy_base.S
index 647e065..0154676 100644
--- a/libc/arch-arm/cortex-a15/bionic/memcpy_base.S
+++ b/libc/arch-arm/cortex-a15/bionic/memcpy_base.S
@@ -53,6 +53,13 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+ENTRY(MEMCPY_BASE)
+ .cfi_startproc
+ .save {r0, lr}
+ .cfi_def_cfa_offset 8
+ .cfi_rel_offset r0, 0
+ .cfi_rel_offset lr, 4
+
// Assumes that n >= 0, and dst, src are valid pointers.
// For any sizes less than 832 use the neon code that doesn't
// care about the src alignment. This avoids any checks
@@ -162,20 +169,34 @@
ands r3, r3, #0x3
bne .L_copy_unknown_alignment
+ .cfi_endproc
+END(MEMCPY_BASE)
+
+ENTRY(MEMCPY_BASE_ALIGNED)
+ .cfi_startproc
+ .save {r0, lr}
+ .cfi_def_cfa_offset 8
+ .cfi_rel_offset r0, 0
+ .cfi_rel_offset lr, 4
+
// To try and improve performance, stack layout changed,
// i.e., not keeping the stack looking like users expect
// (highest numbered register at highest address).
- // TODO: Add debug frame directives.
- // We don't need exception unwind directives, because the code below
- // does not throw any exceptions and does not call any other functions.
- // Generally, newlib functions like this lack debug information for
- // assembler source.
- .save {r4, r5}
strd r4, r5, [sp, #-8]!
- .save {r6, r7}
+ .save {r4, r5}
+ .cfi_adjust_cfa_offset 8
+ .cfi_rel_offset r4, 0
+ .cfi_rel_offset r5, 4
strd r6, r7, [sp, #-8]!
- .save {r8, r9}
+ .save {r6, r7}
+ .cfi_adjust_cfa_offset 8
+ .cfi_rel_offset r6, 0
+ .cfi_rel_offset r7, 0
strd r8, r9, [sp, #-8]!
+ .save {r8, r9}
+ .cfi_adjust_cfa_offset 8
+ .cfi_rel_offset r8, 0
+ .cfi_rel_offset r9, 4
// Optimized for already aligned dst code.
ands ip, r0, #3
@@ -301,3 +322,6 @@
// Src is guaranteed to be at least word aligned by this point.
b .L_word_aligned
+
+ .cfi_endproc
+END(MEMCPY_BASE_ALIGNED)
diff --git a/libc/arch-arm/cortex-a15/bionic/memset.S b/libc/arch-arm/cortex-a15/bionic/memset.S
index 5593be6..b5fc6ba 100644
--- a/libc/arch-arm/cortex-a15/bionic/memset.S
+++ b/libc/arch-arm/cortex-a15/bionic/memset.S
@@ -45,6 +45,7 @@
bls .L_done
// Preserve lr for backtrace.
+ .save {lr}
push {lr}
.cfi_def_cfa_offset 4
.cfi_rel_offset lr, 0
@@ -73,6 +74,7 @@
ENTRY(memset)
.cfi_startproc
+ .save {r0}
stmfd sp!, {r0}
.cfi_def_cfa_offset 4
.cfi_rel_offset r0, 0
diff --git a/libc/arch-arm/cortex-a15/bionic/strcmp.S b/libc/arch-arm/cortex-a15/bionic/strcmp.S
index 7aff7c4..13b329f 100644
--- a/libc/arch-arm/cortex-a15/bionic/strcmp.S
+++ b/libc/arch-arm/cortex-a15/bionic/strcmp.S
@@ -123,8 +123,13 @@
.macro init
/* Macro to save temporary registers and prepare magic values. */
subs sp, sp, #16
+ .cfi_def_cfa_offset 16
strd r4, r5, [sp, #8]
+ .cfi_rel_offset r4, 0
+ .cfi_rel_offset r5, 4
strd r6, r7, [sp]
+ .cfi_rel_offset r6, 8
+ .cfi_rel_offset r7, 12
mvn r6, #0 /* all F */
mov r7, #0 /* all 0 */
.endm /* init */
@@ -165,18 +170,20 @@
#endif /* not __ARMEB__ */
.endm /* setup_return */
+ .cfi_startproc
pld [r0, #0]
pld [r1, #0]
/* Are both strings double-word aligned? */
orr ip, r0, r1
tst ip, #7
- bne do_align
+ bne .L_do_align
/* Fast path. */
+ .save {r4-r7}
init
-doubleword_aligned:
+.L_doubleword_aligned:
/* Get here when the strings to compare are double-word aligned. */
/* Compare two words in every iteration. */
@@ -189,14 +196,14 @@
ldrd r2, r3, [r0], #8
ldrd r4, r5, [r1], #8
- magic_compare_and_branch w1=r2, w2=r4, label=return_24
- magic_compare_and_branch w1=r3, w2=r5, label=return_35
+ magic_compare_and_branch w1=r2, w2=r4, label=.L_return_24
+ magic_compare_and_branch w1=r3, w2=r5, label=.L_return_35
b 2b
-do_align:
+.L_do_align:
/* Is the first string word-aligned? */
ands ip, r0, #3
- beq word_aligned_r0
+ beq .L_word_aligned_r0
/* Fast compare byte by byte until the first string is word-aligned. */
/* The offset of r0 from a word boundary is in ip. Thus, the number of bytes
@@ -204,58 +211,58 @@
bic r0, r0, #3
ldr r2, [r0], #4
lsls ip, ip, #31
- beq byte2
- bcs byte3
+ beq .L_byte2
+ bcs .L_byte3
-byte1:
+.L_byte1:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE1_OFFSET
subs ip, r3, ip
- bne fast_return
- m_cbz reg=r3, label=fast_return
+ bne .L_fast_return
+ m_cbz reg=r3, label=.L_fast_return
-byte2:
+.L_byte2:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE2_OFFSET
subs ip, r3, ip
- bne fast_return
- m_cbz reg=r3, label=fast_return
+ bne .L_fast_return
+ m_cbz reg=r3, label=.L_fast_return
-byte3:
+.L_byte3:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE3_OFFSET
subs ip, r3, ip
- bne fast_return
- m_cbnz reg=r3, label=word_aligned_r0
+ bne .L_fast_return
+ m_cbnz reg=r3, label=.L_word_aligned_r0
-fast_return:
+.L_fast_return:
mov r0, ip
bx lr
-word_aligned_r0:
+.L_word_aligned_r0:
init
/* The first string is word-aligned. */
/* Is the second string word-aligned? */
ands ip, r1, #3
- bne strcmp_unaligned
+ bne .L_strcmp_unaligned
-word_aligned:
+.L_word_aligned:
/* The strings are word-aligned. */
/* Is the first string double-word aligned? */
tst r0, #4
- beq doubleword_aligned_r0
+ beq .L_doubleword_aligned_r0
/* If r0 is not double-word aligned yet, align it by loading
and comparing the next word from each string. */
ldr r2, [r0], #4
ldr r4, [r1], #4
- magic_compare_and_branch w1=r2 w2=r4 label=return_24
+ magic_compare_and_branch w1=r2 w2=r4 label=.L_return_24
-doubleword_aligned_r0:
+.L_doubleword_aligned_r0:
/* Get here when r0 is double-word aligned. */
/* Is r1 doubleword_aligned? */
tst r1, #4
- beq doubleword_aligned
+ beq .L_doubleword_aligned
/* Get here when the strings to compare are word-aligned,
r0 is double-word aligned, but r1 is not double-word aligned. */
@@ -271,9 +278,9 @@
/* Load the next double-word from each string and compare. */
ldrd r2, r3, [r0], #8
- magic_compare_and_branch w1=r2 w2=r5 label=return_25
+ magic_compare_and_branch w1=r2 w2=r5 label=.L_return_25
ldrd r4, r5, [r1], #8
- magic_compare_and_branch w1=r3 w2=r4 label=return_34
+ magic_compare_and_branch w1=r3 w2=r4 label=.L_return_34
b 3b
.macro miscmp_word offsetlo offsethi
@@ -297,47 +304,47 @@
and r2, r3, r6, S2LOMEM #\offsetlo
it eq
cmpeq r2, r5
- bne return_25
+ bne .L_return_25
ldr r5, [r1], #4
cmp ip, #0
eor r3, r2, r3
S2HIMEM r2, r5, #\offsethi
it eq
cmpeq r3, r2
- bne return_32
+ bne .L_return_32
b 7b
.endm /* miscmp_word */
-strcmp_unaligned:
+.L_strcmp_unaligned:
/* r0 is word-aligned, r1 is at offset ip from a word. */
/* Align r1 to the (previous) word-boundary. */
bic r1, r1, #3
/* Unaligned comparison word by word using LDRs. */
cmp ip, #2
- beq miscmp_word_16 /* If ip == 2. */
- bge miscmp_word_24 /* If ip == 3. */
+ beq .L_miscmp_word_16 /* If ip == 2. */
+ bge .L_miscmp_word_24 /* If ip == 3. */
miscmp_word offsetlo=8 offsethi=24 /* If ip == 1. */
-miscmp_word_16: miscmp_word offsetlo=16 offsethi=16
-miscmp_word_24: miscmp_word offsetlo=24 offsethi=8
+.L_miscmp_word_16: miscmp_word offsetlo=16 offsethi=16
+.L_miscmp_word_24: miscmp_word offsetlo=24 offsethi=8
-return_32:
+.L_return_32:
setup_return w1=r3, w2=r2
- b do_return
-return_34:
+ b .L_do_return
+.L_return_34:
setup_return w1=r3, w2=r4
- b do_return
-return_25:
+ b .L_do_return
+.L_return_25:
setup_return w1=r2, w2=r5
- b do_return
-return_35:
+ b .L_do_return
+.L_return_35:
setup_return w1=r3, w2=r5
- b do_return
-return_24:
+ b .L_do_return
+.L_return_24:
setup_return w1=r2, w2=r4
-do_return:
+.L_do_return:
#ifdef __ARMEB__
mov r0, ip
@@ -349,11 +356,16 @@
ldrd r6, r7, [sp]
ldrd r4, r5, [sp, #8]
adds sp, sp, #16
+ .cfi_def_cfa_offset 0
+ .cfi_restore r4
+ .cfi_restore r5
+ .cfi_restore r6
+ .cfi_restore r7
/* There is a zero or a different byte between r1 and r2. */
/* r0 contains a mask of all-zero bytes in r1. */
/* Using r0 and not ip here because cbz requires low register. */
- m_cbz reg=r0, label=compute_return_value
+ m_cbz reg=r0, label=.L_compute_return_value
clz r0, r0
/* r0 contains the number of bits on the left of the first all-zero byte in r1. */
rsb r0, r0, #24
@@ -361,7 +373,7 @@
lsr r1, r1, r0
lsr r2, r2, r0
-compute_return_value:
+.L_compute_return_value:
movs r0, #1
cmp r1, r2
/* The return value is computed as follows.
@@ -374,4 +386,5 @@
it ls
sbcls r0, r0, r0
bx lr
+ .cfi_endproc
END(strcmp)
diff --git a/libc/arch-arm/cortex-a9/bionic/__strcat_chk.S b/libc/arch-arm/cortex-a9/bionic/__strcat_chk.S
index 3f86636..78cf19a 100644
--- a/libc/arch-arm/cortex-a9/bionic/__strcat_chk.S
+++ b/libc/arch-arm/cortex-a9/bionic/__strcat_chk.S
@@ -41,10 +41,12 @@
.cfi_startproc
pld [r0, #0]
push {r0, lr}
+ .save {r0, lr}
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
push {r4, r5}
+ .save {r4, r5}
.cfi_adjust_cfa_offset 8
.cfi_rel_offset r4, 0
.cfi_rel_offset r5, 4
@@ -181,7 +183,7 @@
.L_strlen_done:
add r2, r3, r4
cmp r2, lr
- bgt .L_fortify_check_failed
+ bhi __strcat_chk_fail
// Set up the registers for the memcpy code.
mov r1, r5
@@ -189,13 +191,23 @@
mov r2, r4
add r0, r0, r3
pop {r4, r5}
- .cfi_adjust_cfa_offset -8
- .cfi_restore r4
- .cfi_restore r5
- #include "memcpy_base.S"
+ // Fall through into the memcpy_base function.
+ .cfi_endproc
+END(__strcat_chk)
-.L_fortify_check_failed:
+#define MEMCPY_BASE __strcat_chk_memcpy_base
+#define MEMCPY_BASE_ALIGNED __strcat_chk_memcpy_base_aligned
+#include "memcpy_base.S"
+
+ENTRY(__strcat_chk_fail)
+ .cfi_startproc
+
+ .save {r0, lr}
+ .save {r4, r5}
+ .cfi_def_cfa_offset 8
+ .cfi_rel_offset r0, 0
+ .cfi_rel_offset lr, 4
.cfi_adjust_cfa_offset 8
.cfi_rel_offset r4, 0
.cfi_rel_offset r5, 4
@@ -211,7 +223,7 @@
.word error_string-(1b+4)
.cfi_endproc
-END(__strcat_chk)
+END(__strcat_chk_fail)
.data
error_string:
diff --git a/libc/arch-arm/cortex-a9/bionic/__strcpy_chk.S b/libc/arch-arm/cortex-a9/bionic/__strcpy_chk.S
index 787b057..d0acf1e 100644
--- a/libc/arch-arm/cortex-a9/bionic/__strcpy_chk.S
+++ b/libc/arch-arm/cortex-a9/bionic/__strcpy_chk.S
@@ -40,6 +40,7 @@
.cfi_startproc
pld [r0, #0]
push {r0, lr}
+ .save {r0, lr}
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
@@ -152,26 +153,41 @@
pld [r1, #64]
ldr r0, [sp]
cmp r3, lr
- bge .L_fortify_check_failed
+ bhs __strcpy_chk_fail
// Add 1 for copy length to get the string terminator.
add r2, r3, #1
- #include "memcpy_base.S"
+ .cfi_endproc
-.L_fortify_check_failed:
+ // Fall through into the memcpy_base function.
+END(__strcpy_chk)
+
+#define MEMCPY_BASE __strcpy_chk_memcpy_base
+#define MEMCPY_BASE_ALIGNED __strcpy_chk_memcpy_base_aligned
+#include "memcpy_base.S"
+
+ENTRY(__strcpy_chk_fail)
+ .cfi_startproc
+
+ .save {r0, lr}
+ .cfi_def_cfa_offset 8
+ .cfi_rel_offset r0, 0
+ .cfi_rel_offset lr, 4
+
ldr r0, error_message
ldr r1, error_code
1:
add r0, pc
bl __fortify_chk_fail
+
error_code:
.word BIONIC_EVENT_STRCPY_BUFFER_OVERFLOW
error_message:
.word error_string-(1b+4)
.cfi_endproc
-END(__strcpy_chk)
+END(__strcpy_chk_fail)
.data
error_string:
diff --git a/libc/arch-arm/cortex-a9/bionic/memcpy.S b/libc/arch-arm/cortex-a9/bionic/memcpy.S
index e7beb25..5c4c428 100644
--- a/libc/arch-arm/cortex-a9/bionic/memcpy.S
+++ b/libc/arch-arm/cortex-a9/bionic/memcpy.S
@@ -43,7 +43,7 @@
ENTRY(__memcpy_chk)
.cfi_startproc
cmp r2, r3
- bgt __memcpy_chk_fail
+ bhi __memcpy_chk_fail
// Fall through to memcpy...
.cfi_endproc
@@ -51,21 +51,27 @@
ENTRY(memcpy)
.cfi_startproc
+
pld [r1, #0]
stmfd sp!, {r0, lr}
+ .save {r0, lr}
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
pld [r1, #64]
- #include "memcpy_base.S"
.cfi_endproc
END(memcpy)
+#define MEMCPY_BASE __memcpy_base
+#define MEMCPY_BASE_ALIGNED __memcpy_base_aligned
+#include "memcpy_base.S"
+
+ENTRY(__memcpy_chk_fail)
.cfi_startproc
-__memcpy_chk_fail:
// Preserve lr for backtrace.
push {lr}
+ .save {lr}
.cfi_def_cfa_offset 4
.cfi_rel_offset lr, 0
@@ -79,6 +85,7 @@
error_message:
.word error_string-(1b+4)
.cfi_endproc
+END(__memcpy_chk_fail)
.data
error_string:
diff --git a/libc/arch-arm/cortex-a9/bionic/memcpy_base.S b/libc/arch-arm/cortex-a9/bionic/memcpy_base.S
index 46b5a93..e8ff4f5 100644
--- a/libc/arch-arm/cortex-a9/bionic/memcpy_base.S
+++ b/libc/arch-arm/cortex-a9/bionic/memcpy_base.S
@@ -32,15 +32,21 @@
* cache line.
*/
+ENTRY(MEMCPY_BASE)
+ .cfi_startproc
+ .save {r0, lr}
+ .cfi_def_cfa_offset 8
+ .cfi_rel_offset r0, 0
+ .cfi_rel_offset lr, 4
+
// Check so divider is at least 16 bytes, needed for alignment code.
cmp r2, #16
blo 5f
-
/* check if buffers are aligned. If so, run arm-only version */
eor r3, r0, r1
ands r3, r3, #0x3
- beq 11f
+ beq __memcpy_base_aligned
/* Check the upper size limit for Neon unaligned memory access in memcpy */
cmp r2, #224
@@ -131,9 +137,27 @@
ldmfd sp!, {r0, lr}
bx lr
-11:
+
+ .cfi_endproc
+END(MEMCPY_BASE)
+
+ENTRY(MEMCPY_BASE_ALIGNED)
+ .cfi_startproc
+
+ .save {r0, lr}
+ .cfi_def_cfa_offset 8
+ .cfi_rel_offset r0, 0
+ .cfi_rel_offset lr, 4
+
/* Simple arm-only copy loop to handle aligned copy operations */
- stmfd sp!, {r4, r5, r6, r7, r8}
+ stmfd sp!, {r4-r8}
+ .save {r4-r8}
+ .cfi_adjust_cfa_offset 20
+ .cfi_rel_offset r4, 0
+ .cfi_rel_offset r5, 4
+ .cfi_rel_offset r6, 8
+ .cfi_rel_offset r7, 12
+ .cfi_rel_offset r8, 16
pld [r1, #(32 * 4)]
/* Check alignment */
@@ -202,5 +226,8 @@
ldrbne r3, [r1] /* last byte */
strbne r3, [r0]
6:
- ldmfd sp!, {r4, r5, r6, r7, r8}
+ ldmfd sp!, {r4-r8}
ldmfd sp!, {r0, pc}
+
+ .cfi_endproc
+END(MEMCPY_BASE_ALIGNED)
diff --git a/libc/arch-arm/cortex-a9/bionic/memset.S b/libc/arch-arm/cortex-a9/bionic/memset.S
index bc25a3e..87d2c08 100644
--- a/libc/arch-arm/cortex-a9/bionic/memset.S
+++ b/libc/arch-arm/cortex-a9/bionic/memset.S
@@ -44,6 +44,7 @@
// Preserve lr for backtrace.
push {lr}
+ .save {lr}
.cfi_def_cfa_offset 4
.cfi_rel_offset lr, 0
@@ -73,11 +74,13 @@
/* memset() returns its first argument. */
ENTRY(memset)
.cfi_startproc
+
# The neon memset only wins for less than 132.
cmp r2, #132
- bhi 11f
+ bhi __memset_large_copy
stmfd sp!, {r0}
+ .save {r0}
.cfi_def_cfa_offset 4
.cfi_rel_offset r0, 0
@@ -112,12 +115,18 @@
strcsb r1, [r0], #1
ldmfd sp!, {r0}
bx lr
-11:
+
+ .cfi_endproc
+END(memset)
+
+ENTRY(__memset_large_copy)
+ .cfi_startproc
+
/* compute the offset to align the destination
* offset = (4-(src&3))&3 = -src & 3
*/
-
stmfd sp!, {r0, r4-r7, lr}
+ .save {r0, r4-r7, lr}
.cfi_def_cfa_offset 24
.cfi_rel_offset r0, 0
.cfi_rel_offset r4, 4
@@ -188,7 +197,7 @@
ldmfd sp!, {r0, r4-r7, lr}
bx lr
.cfi_endproc
-END(memset)
+END(__memset_large_copy)
.data
error_string:
diff --git a/libc/arch-arm/cortex-a9/bionic/strcmp.S b/libc/arch-arm/cortex-a9/bionic/strcmp.S
index 9597d0d..232df75 100644
--- a/libc/arch-arm/cortex-a9/bionic/strcmp.S
+++ b/libc/arch-arm/cortex-a9/bionic/strcmp.S
@@ -123,8 +123,13 @@
.macro init
/* Macro to save temporary registers and prepare magic values. */
subs sp, sp, #16
+ .cfi_def_cfa_offset 16
strd r4, r5, [sp, #8]
+ .cfi_rel_offset r4, 0
+ .cfi_rel_offset r5, 4
strd r6, r7, [sp]
+ .cfi_rel_offset r6, 8
+ .cfi_rel_offset r7, 12
mvn r6, #0 /* all F */
mov r7, #0 /* all 0 */
.endm /* init */
@@ -165,18 +170,20 @@
#endif /* not __ARMEB__ */
.endm /* setup_return */
+ .cfi_startproc
pld [r0, #0]
pld [r1, #0]
/* Are both strings double-word aligned? */
orr ip, r0, r1
tst ip, #7
- bne do_align
+ bne .L_do_align
/* Fast path. */
+ .save {r4-r7}
init
-doubleword_aligned:
+.L_doubleword_aligned:
/* Get here when the strings to compare are double-word aligned. */
/* Compare two words in every iteration. */
@@ -189,14 +196,14 @@
ldrd r2, r3, [r0], #8
ldrd r4, r5, [r1], #8
- magic_compare_and_branch w1=r2, w2=r4, label=return_24
- magic_compare_and_branch w1=r3, w2=r5, label=return_35
+ magic_compare_and_branch w1=r2, w2=r4, label=.L_return_24
+ magic_compare_and_branch w1=r3, w2=r5, label=.L_return_35
b 2b
-do_align:
+.L_do_align:
/* Is the first string word-aligned? */
ands ip, r0, #3
- beq word_aligned_r0
+ beq .L_word_aligned_r0
/* Fast compare byte by byte until the first string is word-aligned. */
/* The offset of r0 from a word boundary is in ip. Thus, the number of bytes
@@ -204,58 +211,58 @@
bic r0, r0, #3
ldr r2, [r0], #4
lsls ip, ip, #31
- beq byte2
- bcs byte3
+ beq .L_byte2
+ bcs .L_byte3
-byte1:
+.L_byte1:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE1_OFFSET
subs ip, r3, ip
- bne fast_return
- m_cbz reg=r3, label=fast_return
+ bne .L_fast_return
+ m_cbz reg=r3, label=.L_fast_return
-byte2:
+.L_byte2:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE2_OFFSET
subs ip, r3, ip
- bne fast_return
- m_cbz reg=r3, label=fast_return
+ bne .L_fast_return
+ m_cbz reg=r3, label=.L_fast_return
-byte3:
+.L_byte3:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE3_OFFSET
subs ip, r3, ip
- bne fast_return
- m_cbnz reg=r3, label=word_aligned_r0
+ bne .L_fast_return
+ m_cbnz reg=r3, label=.L_word_aligned_r0
-fast_return:
+.L_fast_return:
mov r0, ip
bx lr
-word_aligned_r0:
+.L_word_aligned_r0:
init
/* The first string is word-aligned. */
/* Is the second string word-aligned? */
ands ip, r1, #3
- bne strcmp_unaligned
+ bne .L_strcmp_unaligned
-word_aligned:
+.L_word_aligned:
/* The strings are word-aligned. */
/* Is the first string double-word aligned? */
tst r0, #4
- beq doubleword_aligned_r0
+ beq .L_doubleword_aligned_r0
/* If r0 is not double-word aligned yet, align it by loading
and comparing the next word from each string. */
ldr r2, [r0], #4
ldr r4, [r1], #4
- magic_compare_and_branch w1=r2 w2=r4 label=return_24
+ magic_compare_and_branch w1=r2 w2=r4 label=.L_return_24
-doubleword_aligned_r0:
+.L_doubleword_aligned_r0:
/* Get here when r0 is double-word aligned. */
/* Is r1 doubleword_aligned? */
tst r1, #4
- beq doubleword_aligned
+ beq .L_doubleword_aligned
/* Get here when the strings to compare are word-aligned,
r0 is double-word aligned, but r1 is not double-word aligned. */
@@ -271,9 +278,9 @@
/* Load the next double-word from each string and compare. */
ldrd r2, r3, [r0], #8
- magic_compare_and_branch w1=r2 w2=r5 label=return_25
+ magic_compare_and_branch w1=r2 w2=r5 label=.L_return_25
ldrd r4, r5, [r1], #8
- magic_compare_and_branch w1=r3 w2=r4 label=return_34
+ magic_compare_and_branch w1=r3 w2=r4 label=.L_return_34
b 3b
.macro miscmp_word offsetlo offsethi
@@ -297,33 +304,33 @@
and r2, r3, r6, S2LOMEM #\offsetlo
it eq
cmpeq r2, r5
- bne return_25
+ bne .L_return_25
ldr r5, [r1], #4
cmp ip, #0
eor r3, r2, r3
S2HIMEM r2, r5, #\offsethi
it eq
cmpeq r3, r2
- bne return_32
+ bne .L_return_32
b 7b
.endm /* miscmp_word */
-return_32:
+.L_return_32:
setup_return w1=r3, w2=r2
- b do_return
-return_34:
+ b .L_do_return
+.L_return_34:
setup_return w1=r3, w2=r4
- b do_return
-return_25:
+ b .L_do_return
+.L_return_25:
setup_return w1=r2, w2=r5
- b do_return
-return_35:
+ b .L_do_return
+.L_return_35:
setup_return w1=r3, w2=r5
- b do_return
-return_24:
+ b .L_do_return
+.L_return_24:
setup_return w1=r2, w2=r4
-do_return:
+.L_do_return:
#ifdef __ARMEB__
mov r0, ip
@@ -335,11 +342,16 @@
ldrd r6, r7, [sp]
ldrd r4, r5, [sp, #8]
adds sp, sp, #16
+ .cfi_def_cfa_offset 0
+ .cfi_restore r4
+ .cfi_restore r5
+ .cfi_restore r6
+ .cfi_restore r7
/* There is a zero or a different byte between r1 and r2. */
/* r0 contains a mask of all-zero bytes in r1. */
/* Using r0 and not ip here because cbz requires low register. */
- m_cbz reg=r0, label=compute_return_value
+ m_cbz reg=r0, label=.L_compute_return_value
clz r0, r0
/* r0 contains the number of bits on the left of the first all-zero byte in r1. */
rsb r0, r0, #24
@@ -347,7 +359,7 @@
lsr r1, r1, r0
lsr r2, r2, r0
-compute_return_value:
+.L_compute_return_value:
movs r0, #1
cmp r1, r2
/* The return value is computed as follows.
@@ -367,7 +379,7 @@
* bionic/libc/arch-arm/cortex-a15/bionic/strcmp.S for the unedited
* version of the code.
*/
-strcmp_unaligned:
+.L_strcmp_unaligned:
wp1 .req r0
wp2 .req r1
b1 .req r2
@@ -520,6 +532,11 @@
ldrd r6, r7, [sp]
ldrd r4, r5, [sp, #8]
adds sp, sp, #16
+ .cfi_def_cfa_offset 0
+ .cfi_restore r4
+ .cfi_restore r5
+ .cfi_restore r6
+ .cfi_restore r7
bx lr
@@ -541,4 +558,5 @@
adds sp, sp, #16
bx lr
+ .cfi_endproc
END(strcmp)
diff --git a/libc/arch-arm/krait/bionic/__strcat_chk.S b/libc/arch-arm/krait/bionic/__strcat_chk.S
index 4516d30..956b461 100644
--- a/libc/arch-arm/krait/bionic/__strcat_chk.S
+++ b/libc/arch-arm/krait/bionic/__strcat_chk.S
@@ -41,10 +41,12 @@
.cfi_startproc
pld [r0, #0]
push {r0, lr}
+ .save {r0, lr}
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
push {r4, r5}
+ .save {r4, r5}
.cfi_adjust_cfa_offset 8
.cfi_rel_offset r4, 0
.cfi_rel_offset r5, 4
@@ -178,7 +180,7 @@
.L_strlen_done:
add r2, r3, r4
cmp r2, lr
- bgt .L_fortify_check_failed
+ bhi __strcat_chk_failed
// Set up the registers for the memcpy code.
mov r1, r5
@@ -186,13 +188,21 @@
mov r2, r4
add r0, r0, r3
pop {r4, r5}
- .cfi_adjust_cfa_offset -8
- .cfi_restore r4
- .cfi_restore r5
- #include "memcpy_base.S"
+ .cfi_endproc
+END(__strcat_chk)
-.L_fortify_check_failed:
+#define MEMCPY_BASE __strcat_chk_memcpy_base
+#define MEMCPY_BASE_ALIGNED __strcat_chk_memcpy_base_aligned
+#include "memcpy_base.S"
+
+ENTRY(__strcat_chk_failed)
+ .cfi_startproc
+ .save {r0, lr}
+ .save {r4, r5}
+ .cfi_def_cfa_offset 8
+ .cfi_rel_offset r0, 0
+ .cfi_rel_offset lr, 4
.cfi_adjust_cfa_offset 8
.cfi_rel_offset r4, 0
.cfi_rel_offset r5, 4
@@ -208,7 +218,7 @@
.word error_string-(1b+4)
.cfi_endproc
-END(__strcat_chk)
+END(__strcat_chk_failed)
.data
error_string:
diff --git a/libc/arch-arm/krait/bionic/__strcpy_chk.S b/libc/arch-arm/krait/bionic/__strcpy_chk.S
index c57268c..402cac6 100644
--- a/libc/arch-arm/krait/bionic/__strcpy_chk.S
+++ b/libc/arch-arm/krait/bionic/__strcpy_chk.S
@@ -40,6 +40,7 @@
.cfi_startproc
pld [r0, #0]
push {r0, lr}
+ .save {r0, lr}
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
@@ -150,14 +151,25 @@
pld [r1, #64]
ldr r0, [sp]
cmp r3, lr
- bge .L_fortify_check_failed
+ bhs __strcpy_chk_failed
// Add 1 for copy length to get the string terminator.
add r2, r3, #1
- #include "memcpy_base.S"
+ .cfi_endproc
+END(__strcpy_chk)
-.L_fortify_check_failed:
+#define MEMCPY_BASE __strcpy_chk_memcpy_base
+#define MEMCPY_BASE_ALIGNED __strcpy_chk_memcpy_base_aligned
+#include "memcpy_base.S"
+
+ENTRY(__strcpy_chk_failed)
+ .cfi_startproc
+ .save {r0, lr}
+ .cfi_def_cfa_offset 8
+ .cfi_rel_offset r0, 0
+ .cfi_rel_offset lr, 4
+
ldr r0, error_message
ldr r1, error_code
1:
@@ -168,7 +180,7 @@
error_message:
.word error_string-(1b+4)
.cfi_endproc
-END(__strcpy_chk)
+END(__strcpy_chk_failed)
.data
error_string:
diff --git a/libc/arch-arm/krait/bionic/memcpy.S b/libc/arch-arm/krait/bionic/memcpy.S
index 75b2395..ea040bc 100644
--- a/libc/arch-arm/krait/bionic/memcpy.S
+++ b/libc/arch-arm/krait/bionic/memcpy.S
@@ -46,7 +46,7 @@
ENTRY(__memcpy_chk)
.cfi_startproc
cmp r2, r3
- bgt __memcpy_chk_fail
+ bhi __memcpy_chk_fail
// Fall through to memcpy...
.cfi_endproc
@@ -56,18 +56,22 @@
.cfi_startproc
pld [r1, #64]
stmfd sp!, {r0, lr}
+ .save {r0, lr}
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
-
- #include "memcpy_base.S"
.cfi_endproc
END(memcpy)
+#define MEMCPY_BASE __memcpy_base
+#define MEMCPY_BASE_ALIGNED __memcpy_base_aligned
+#include "memcpy_base.S"
+
+ENTRY(__memcpy_chk_fail)
.cfi_startproc
-__memcpy_chk_fail:
// Preserve lr for backtrace.
push {lr}
+ .save {lr}
.cfi_def_cfa_offset 4
.cfi_rel_offset lr, 0
@@ -81,6 +85,7 @@
error_message:
.word error_string-(1b+4)
.cfi_endproc
+END(__memcpy_chk_fail)
.data
error_string:
diff --git a/libc/arch-arm/krait/bionic/memcpy_base.S b/libc/arch-arm/krait/bionic/memcpy_base.S
index 48ce477..d87a542 100644
--- a/libc/arch-arm/krait/bionic/memcpy_base.S
+++ b/libc/arch-arm/krait/bionic/memcpy_base.S
@@ -35,6 +35,13 @@
// Assumes neon instructions and a cache line size of 32 bytes.
+ENTRY(MEMCPY_BASE)
+ .cfi_startproc
+ .save {r0, lr}
+ .cfi_def_cfa_offset 8
+ .cfi_rel_offset r0, 0
+ .cfi_rel_offset lr, 4
+
/* do we have at least 16-bytes to copy (needed for alignment below) */
cmp r2, #16
blo 5f
@@ -115,3 +122,6 @@
ldmfd sp!, {r0, lr}
bx lr
+
+ .cfi_endproc
+END(MEMCPY_BASE)
diff --git a/libc/arch-arm/krait/bionic/memset.S b/libc/arch-arm/krait/bionic/memset.S
index 1566132..005dfd8 100644
--- a/libc/arch-arm/krait/bionic/memset.S
+++ b/libc/arch-arm/krait/bionic/memset.S
@@ -44,6 +44,7 @@
bls .L_done
// Preserve lr for backtrace.
+ .save {lr}
push {lr}
.cfi_def_cfa_offset 4
.cfi_rel_offset lr, 0
@@ -74,6 +75,7 @@
/* memset() returns its first argument. */
ENTRY(memset)
.cfi_startproc
+ .save {r0}
stmfd sp!, {r0}
.cfi_def_cfa_offset 4
.cfi_rel_offset r0, 0
diff --git a/libc/arch-arm/krait/bionic/strcmp.S b/libc/arch-arm/krait/bionic/strcmp.S
index d614b9d..d4cf3f4 100644
--- a/libc/arch-arm/krait/bionic/strcmp.S
+++ b/libc/arch-arm/krait/bionic/strcmp.S
@@ -123,8 +123,13 @@
.macro init
/* Macro to save temporary registers and prepare magic values. */
subs sp, sp, #16
+ .cfi_def_cfa_offset 16
strd r4, r5, [sp, #8]
+ .cfi_rel_offset r4, 0
+ .cfi_rel_offset r5, 4
strd r6, r7, [sp]
+ .cfi_rel_offset r6, 8
+ .cfi_rel_offset r7, 12
mvn r6, #0 /* all F */
mov r7, #0 /* all 0 */
.endm /* init */
@@ -165,18 +170,20 @@
#endif /* not __ARMEB__ */
.endm /* setup_return */
+ .cfi_startproc
pld [r0, #0]
pld [r1, #0]
/* Are both strings double-word aligned? */
orr ip, r0, r1
tst ip, #7
- bne do_align
+ bne .L_do_align
/* Fast path. */
+ .save {r4-r7}
init
-doubleword_aligned:
+.L_doubleword_aligned:
/* Get here when the strings to compare are double-word aligned. */
/* Compare two words in every iteration. */
@@ -189,14 +196,14 @@
ldrd r2, r3, [r0], #8
ldrd r4, r5, [r1], #8
- magic_compare_and_branch w1=r2, w2=r4, label=return_24
- magic_compare_and_branch w1=r3, w2=r5, label=return_35
+ magic_compare_and_branch w1=r2, w2=r4, label=.L_return_24
+ magic_compare_and_branch w1=r3, w2=r5, label=.L_return_35
b 2b
-do_align:
+.L_do_align:
/* Is the first string word-aligned? */
ands ip, r0, #3
- beq word_aligned_r0
+ beq .L_word_aligned_r0
/* Fast compare byte by byte until the first string is word-aligned. */
/* The offset of r0 from a word boundary is in ip. Thus, the number of bytes
@@ -204,58 +211,58 @@
bic r0, r0, #3
ldr r2, [r0], #4
lsls ip, ip, #31
- beq byte2
- bcs byte3
+ beq .L_byte2
+ bcs .L_byte3
-byte1:
+.L_byte1:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE1_OFFSET
subs ip, r3, ip
- bne fast_return
- m_cbz reg=r3, label=fast_return
+ bne .L_fast_return
+ m_cbz reg=r3, label=.L_fast_return
-byte2:
+.L_byte2:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE2_OFFSET
subs ip, r3, ip
- bne fast_return
- m_cbz reg=r3, label=fast_return
+ bne .L_fast_return
+ m_cbz reg=r3, label=.L_fast_return
-byte3:
+.L_byte3:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE3_OFFSET
subs ip, r3, ip
- bne fast_return
- m_cbnz reg=r3, label=word_aligned_r0
+ bne .L_fast_return
+ m_cbnz reg=r3, label=.L_word_aligned_r0
-fast_return:
+.L_fast_return:
mov r0, ip
bx lr
-word_aligned_r0:
+.L_word_aligned_r0:
init
/* The first string is word-aligned. */
/* Is the second string word-aligned? */
ands ip, r1, #3
- bne strcmp_unaligned
+ bne .L_strcmp_unaligned
-word_aligned:
+.L_word_aligned:
/* The strings are word-aligned. */
/* Is the first string double-word aligned? */
tst r0, #4
- beq doubleword_aligned_r0
+ beq .L_doubleword_aligned_r0
/* If r0 is not double-word aligned yet, align it by loading
and comparing the next word from each string. */
ldr r2, [r0], #4
ldr r4, [r1], #4
- magic_compare_and_branch w1=r2 w2=r4 label=return_24
+ magic_compare_and_branch w1=r2 w2=r4 label=.L_return_24
-doubleword_aligned_r0:
+.L_doubleword_aligned_r0:
/* Get here when r0 is double-word aligned. */
/* Is r1 doubleword_aligned? */
tst r1, #4
- beq doubleword_aligned
+ beq .L_doubleword_aligned
/* Get here when the strings to compare are word-aligned,
r0 is double-word aligned, but r1 is not double-word aligned. */
@@ -271,9 +278,9 @@
/* Load the next double-word from each string and compare. */
ldrd r2, r3, [r0], #8
- magic_compare_and_branch w1=r2 w2=r5 label=return_25
+ magic_compare_and_branch w1=r2 w2=r5 label=.L_return_25
ldrd r4, r5, [r1], #8
- magic_compare_and_branch w1=r3 w2=r4 label=return_34
+ magic_compare_and_branch w1=r3 w2=r4 label=.L_return_34
b 3b
.macro miscmp_word offsetlo offsethi
@@ -297,46 +304,46 @@
and r2, r3, r6, S2LOMEM #\offsetlo
it eq
cmpeq r2, r5
- bne return_25
+ bne .L_return_25
ldr r5, [r1], #4
cmp ip, #0
eor r3, r2, r3
S2HIMEM r2, r5, #\offsethi
it eq
cmpeq r3, r2
- bne return_32
+ bne .L_return_32
b 7b
.endm /* miscmp_word */
-strcmp_unaligned:
+.L_strcmp_unaligned:
/* r0 is word-aligned, r1 is at offset ip from a word. */
/* Align r1 to the (previous) word-boundary. */
bic r1, r1, #3
/* Unaligned comparison word by word using LDRs. */
cmp ip, #2
- beq miscmp_word_16 /* If ip == 2. */
- bge miscmp_word_24 /* If ip == 3. */
+ beq .L_miscmp_word_16 /* If ip == 2. */
+ bge .L_miscmp_word_24 /* If ip == 3. */
miscmp_word offsetlo=8 offsethi=24 /* If ip == 1. */
-miscmp_word_24: miscmp_word offsetlo=24 offsethi=8
+.L_miscmp_word_24: miscmp_word offsetlo=24 offsethi=8
-return_32:
+.L_return_32:
setup_return w1=r3, w2=r2
- b do_return
-return_34:
+ b .L_do_return
+.L_return_34:
setup_return w1=r3, w2=r4
- b do_return
-return_25:
+ b .L_do_return
+.L_return_25:
setup_return w1=r2, w2=r5
- b do_return
-return_35:
+ b .L_do_return
+.L_return_35:
setup_return w1=r3, w2=r5
- b do_return
-return_24:
+ b .L_do_return
+.L_return_24:
setup_return w1=r2, w2=r4
-do_return:
+.L_do_return:
#ifdef __ARMEB__
mov r0, ip
@@ -348,11 +355,16 @@
ldrd r6, r7, [sp]
ldrd r4, r5, [sp, #8]
adds sp, sp, #16
+ .cfi_def_cfa_offset 0
+ .cfi_restore r4
+ .cfi_restore r5
+ .cfi_restore r6
+ .cfi_restore r7
/* There is a zero or a different byte between r1 and r2. */
/* r0 contains a mask of all-zero bytes in r1. */
/* Using r0 and not ip here because cbz requires low register. */
- m_cbz reg=r0, label=compute_return_value
+ m_cbz reg=r0, label=.L_compute_return_value
clz r0, r0
/* r0 contains the number of bits on the left of the first all-zero byte in r1. */
rsb r0, r0, #24
@@ -360,7 +372,7 @@
lsr r1, r1, r0
lsr r2, r2, r0
-compute_return_value:
+.L_compute_return_value:
movs r0, #1
cmp r1, r2
/* The return value is computed as follows.
@@ -380,7 +392,7 @@
* previous version. See bionic/libc/arch-arm/cortex-a15/bionic/strcmp.S
* for the unedited version of this code.
*/
-miscmp_word_16:
+.L_miscmp_word_16:
wp1 .req r0
wp2 .req r1
b1 .req r2
@@ -453,6 +465,11 @@
ldrd r6, r7, [sp]
ldrd r4, r5, [sp, #8]
adds sp, sp, #16
+ .cfi_def_cfa_offset 0
+ .cfi_restore r4
+ .cfi_restore r5
+ .cfi_restore r6
+ .cfi_restore r7
bx lr
@@ -472,6 +489,12 @@
ldrd r6, r7, [sp]
ldrd r4, r5, [sp, #8]
adds sp, sp, #16
+ .cfi_def_cfa_offset 0
+ .cfi_restore r4
+ .cfi_restore r5
+ .cfi_restore r6
+ .cfi_restore r7
bx lr
+ .cfi_endproc
END(strcmp)
diff --git a/libc/arch-arm/syscalls.mk b/libc/arch-arm/syscalls.mk
index 252a428..33e520f 100644
--- a/libc/arch-arm/syscalls.mk
+++ b/libc/arch-arm/syscalls.mk
@@ -84,6 +84,7 @@
syscall_src += arch-arm/syscalls/__fcntl64.S
syscall_src += arch-arm/syscalls/__fstatfs64.S
syscall_src += arch-arm/syscalls/sendfile.S
+syscall_src += arch-arm/syscalls/sendfile64.S
syscall_src += arch-arm/syscalls/fstatat.S
syscall_src += arch-arm/syscalls/mkdirat.S
syscall_src += arch-arm/syscalls/fchownat.S
@@ -116,6 +117,7 @@
syscall_src += arch-arm/syscalls/symlink.S
syscall_src += arch-arm/syscalls/fchdir.S
syscall_src += arch-arm/syscalls/truncate.S
+syscall_src += arch-arm/syscalls/truncate64.S
syscall_src += arch-arm/syscalls/setxattr.S
syscall_src += arch-arm/syscalls/lsetxattr.S
syscall_src += arch-arm/syscalls/getxattr.S
diff --git a/libc/arch-arm/syscalls/sendfile64.S b/libc/arch-arm/syscalls/sendfile64.S
new file mode 100644
index 0000000..87de344
--- /dev/null
+++ b/libc/arch-arm/syscalls/sendfile64.S
@@ -0,0 +1,15 @@
+/* autogenerated by gensyscalls.py */
+#include <asm/unistd.h>
+#include <linux/err.h>
+#include <machine/asm.h>
+
+ENTRY(sendfile64)
+ mov ip, r7
+ ldr r7, =__NR_sendfile64
+ swi #0
+ mov r7, ip
+ cmn r0, #(MAX_ERRNO + 1)
+ bxls lr
+ neg r0, r0
+ b __set_errno
+END(sendfile64)
diff --git a/libc/arch-arm/syscalls/truncate64.S b/libc/arch-arm/syscalls/truncate64.S
new file mode 100644
index 0000000..059bd97
--- /dev/null
+++ b/libc/arch-arm/syscalls/truncate64.S
@@ -0,0 +1,15 @@
+/* autogenerated by gensyscalls.py */
+#include <asm/unistd.h>
+#include <linux/err.h>
+#include <machine/asm.h>
+
+ENTRY(truncate64)
+ mov ip, r7
+ ldr r7, =__NR_truncate64
+ swi #0
+ mov r7, ip
+ cmn r0, #(MAX_ERRNO + 1)
+ bxls lr
+ neg r0, r0
+ b __set_errno
+END(truncate64)
diff --git a/libc/arch-mips/syscalls.mk b/libc/arch-mips/syscalls.mk
index 23393a2..b34b0a9 100644
--- a/libc/arch-mips/syscalls.mk
+++ b/libc/arch-mips/syscalls.mk
@@ -87,6 +87,7 @@
syscall_src += arch-mips/syscalls/__fcntl64.S
syscall_src += arch-mips/syscalls/__fstatfs64.S
syscall_src += arch-mips/syscalls/sendfile.S
+syscall_src += arch-mips/syscalls/sendfile64.S
syscall_src += arch-mips/syscalls/fstatat.S
syscall_src += arch-mips/syscalls/mkdirat.S
syscall_src += arch-mips/syscalls/fchownat.S
@@ -119,6 +120,7 @@
syscall_src += arch-mips/syscalls/symlink.S
syscall_src += arch-mips/syscalls/fchdir.S
syscall_src += arch-mips/syscalls/truncate.S
+syscall_src += arch-mips/syscalls/truncate64.S
syscall_src += arch-mips/syscalls/setxattr.S
syscall_src += arch-mips/syscalls/lsetxattr.S
syscall_src += arch-mips/syscalls/getxattr.S
diff --git a/libc/arch-mips/syscalls/sendfile64.S b/libc/arch-mips/syscalls/sendfile64.S
new file mode 100644
index 0000000..5b74709
--- /dev/null
+++ b/libc/arch-mips/syscalls/sendfile64.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <asm/unistd.h>
+ .text
+ .globl sendfile64
+ .align 4
+ .ent sendfile64
+
+sendfile64:
+ .set noreorder
+ .cpload $t9
+ li $v0, __NR_sendfile64
+ syscall
+ bnez $a3, 1f
+ move $a0, $v0
+ j $ra
+ nop
+1:
+ la $t9,__set_errno
+ j $t9
+ nop
+ .set reorder
+ .end sendfile64
diff --git a/libc/arch-mips/syscalls/truncate64.S b/libc/arch-mips/syscalls/truncate64.S
new file mode 100644
index 0000000..57f0b5f
--- /dev/null
+++ b/libc/arch-mips/syscalls/truncate64.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <asm/unistd.h>
+ .text
+ .globl truncate64
+ .align 4
+ .ent truncate64
+
+truncate64:
+ .set noreorder
+ .cpload $t9
+ li $v0, __NR_truncate64
+ syscall
+ bnez $a3, 1f
+ move $a0, $v0
+ j $ra
+ nop
+1:
+ la $t9,__set_errno
+ j $t9
+ nop
+ .set reorder
+ .end truncate64
diff --git a/libc/arch-x86/syscalls.mk b/libc/arch-x86/syscalls.mk
index 11573de..7180cf2 100644
--- a/libc/arch-x86/syscalls.mk
+++ b/libc/arch-x86/syscalls.mk
@@ -88,6 +88,7 @@
syscall_src += arch-x86/syscalls/__fcntl64.S
syscall_src += arch-x86/syscalls/__fstatfs64.S
syscall_src += arch-x86/syscalls/sendfile.S
+syscall_src += arch-x86/syscalls/sendfile64.S
syscall_src += arch-x86/syscalls/fstatat.S
syscall_src += arch-x86/syscalls/mkdirat.S
syscall_src += arch-x86/syscalls/fchownat.S
@@ -120,6 +121,7 @@
syscall_src += arch-x86/syscalls/symlink.S
syscall_src += arch-x86/syscalls/fchdir.S
syscall_src += arch-x86/syscalls/truncate.S
+syscall_src += arch-x86/syscalls/truncate64.S
syscall_src += arch-x86/syscalls/setxattr.S
syscall_src += arch-x86/syscalls/lsetxattr.S
syscall_src += arch-x86/syscalls/getxattr.S
diff --git a/libc/arch-x86/syscalls/sendfile64.S b/libc/arch-x86/syscalls/sendfile64.S
new file mode 100644
index 0000000..9731806
--- /dev/null
+++ b/libc/arch-x86/syscalls/sendfile64.S
@@ -0,0 +1,30 @@
+/* autogenerated by gensyscalls.py */
+#include <linux/err.h>
+#include <machine/asm.h>
+#include <asm/unistd.h>
+
+ENTRY(sendfile64)
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ pushl %esi
+ mov 20(%esp), %ebx
+ mov 24(%esp), %ecx
+ mov 28(%esp), %edx
+ mov 32(%esp), %esi
+ movl $__NR_sendfile64, %eax
+ int $0x80
+ cmpl $-MAX_ERRNO, %eax
+ jb 1f
+ negl %eax
+ pushl %eax
+ call __set_errno
+ addl $4, %esp
+ orl $-1, %eax
+1:
+ popl %esi
+ popl %edx
+ popl %ecx
+ popl %ebx
+ ret
+END(sendfile64)
diff --git a/libc/arch-x86/syscalls/truncate64.S b/libc/arch-x86/syscalls/truncate64.S
new file mode 100644
index 0000000..f9118bb
--- /dev/null
+++ b/libc/arch-x86/syscalls/truncate64.S
@@ -0,0 +1,27 @@
+/* autogenerated by gensyscalls.py */
+#include <linux/err.h>
+#include <machine/asm.h>
+#include <asm/unistd.h>
+
+ENTRY(truncate64)
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ mov 16(%esp), %ebx
+ mov 20(%esp), %ecx
+ mov 24(%esp), %edx
+ movl $__NR_truncate64, %eax
+ int $0x80
+ cmpl $-MAX_ERRNO, %eax
+ jb 1f
+ negl %eax
+ pushl %eax
+ call __set_errno
+ addl $4, %esp
+ orl $-1, %eax
+1:
+ popl %edx
+ popl %ecx
+ popl %ebx
+ ret
+END(truncate64)
diff --git a/libc/arch-x86/x86.mk b/libc/arch-x86/x86.mk
index 19c1402..ada5d69 100644
--- a/libc/arch-x86/x86.mk
+++ b/libc/arch-x86/x86.mk
@@ -72,7 +72,7 @@
arch-x86/string/bzero.S \
bionic/memrchr.c \
bionic/memchr.c \
- string/strchr.cpp \
+ bionic/strchr.cpp \
string/strrchr.c \
string/index.c \
bionic/strnlen.c \
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index 1fc490e..714d0bc 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -37,6 +37,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/auxv.h>
+#include <sys/time.h>
+#include <sys/resource.h>
#include <unistd.h>
#include "atexit.h"
@@ -58,9 +60,16 @@
// Declared in <private/bionic_ssp.h>.
uintptr_t __stack_chk_guard = 0;
-// Declared in <asm/page.h>.
-unsigned int __page_size = PAGE_SIZE;
-unsigned int __page_shift = PAGE_SHIFT;
+static size_t get_main_thread_stack_size() {
+ rlimit stack_limit;
+ int rlimit_result = getrlimit(RLIMIT_STACK, &stack_limit);
+ if ((rlimit_result == 0) &&
+ (stack_limit.rlim_cur != RLIM_INFINITY) &&
+ (stack_limit.rlim_cur > PTHREAD_STACK_MIN)) {
+ return (stack_limit.rlim_cur & ~(PAGE_SIZE - 1));
+ }
+ return PTHREAD_STACK_SIZE_DEFAULT;
+}
/* Init TLS for the initial thread. Called by the linker _before_ libc is mapped
* in memory. Beware: all writes to libc globals from this function will
@@ -76,9 +85,9 @@
void __libc_init_tls(KernelArgumentBlock& args) {
__libc_auxv = args.auxv;
- unsigned stack_top = (__get_sp() & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
- unsigned stack_size = 128 * 1024;
- unsigned stack_bottom = stack_top - stack_size;
+ uintptr_t stack_top = (__get_sp() & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
+ size_t stack_size = get_main_thread_stack_size();
+ uintptr_t stack_bottom = stack_top - stack_size;
static void* tls[BIONIC_TLS_SLOTS];
static pthread_internal_t thread;
diff --git a/libc/bionic/libc_init_common.h b/libc/bionic/libc_init_common.h
index 14105f8..59dc7df 100644
--- a/libc/bionic/libc_init_common.h
+++ b/libc/bionic/libc_init_common.h
@@ -49,7 +49,7 @@
__END_DECLS
#if defined(__cplusplus)
-struct KernelArgumentBlock;
+class KernelArgumentBlock;
void __LIBC_HIDDEN__ __libc_init_common(KernelArgumentBlock& args);
#endif
diff --git a/libc/bionic/lseek64.c b/libc/bionic/lseek64.c
index db0c413..c24ae64 100644
--- a/libc/bionic/lseek64.c
+++ b/libc/bionic/lseek64.c
@@ -25,16 +25,16 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
+
#include <unistd.h>
-extern int __llseek(int fd, unsigned long offset_hi, unsigned long offset_lo, loff_t* result, int whence);
+extern int __llseek(int fd, unsigned long offset_hi, unsigned long offset_lo, off64_t* result, int whence);
-off64_t lseek64(int fd, off64_t off, int whence)
-{
- loff_t result;
+off64_t lseek64(int fd, off64_t off, int whence) {
+ off64_t result;
+ if (__llseek(fd, (unsigned long)(off >> 32),(unsigned long)(off), &result, whence) < 0) {
+ return -1;
+ }
- if ( __llseek(fd, (unsigned long)(off >> 32),(unsigned long)(off), &result, whence ) < 0 )
- return -1;
-
- return result;
+ return result;
}
diff --git a/libc/bionic/mmap.cpp b/libc/bionic/mmap.cpp
index febc459..75bea58 100644
--- a/libc/bionic/mmap.cpp
+++ b/libc/bionic/mmap.cpp
@@ -37,13 +37,13 @@
#define MMAP2_SHIFT 12 // 2**12 == 4096
-void* mmap(void* addr, size_t size, int prot, int flags, int fd, off_t offset) {
+void* mmap64(void* addr, size_t size, int prot, int flags, int fd, off64_t offset) {
if (offset & ((1UL << MMAP2_SHIFT)-1)) {
errno = EINVAL;
return MAP_FAILED;
}
- size_t unsigned_offset = static_cast<size_t>(offset); // To avoid sign extension.
+ uint64_t unsigned_offset = static_cast<uint64_t>(offset); // To avoid sign extension.
void* result = __mmap2(addr, size, prot, flags, fd, unsigned_offset >> MMAP2_SHIFT);
if (result != MAP_FAILED && (flags & (MAP_PRIVATE | MAP_ANONYMOUS)) != 0) {
@@ -53,3 +53,7 @@
return result;
}
+
+void* mmap(void* addr, size_t size, int prot, int flags, int fd, off_t offset) {
+ return mmap64(addr, size, prot, flags, fd, static_cast<off64_t>(offset));
+}
diff --git a/libc/bionic/pthread_attr.cpp b/libc/bionic/pthread_attr.cpp
index d7c6c13..2763b0c 100644
--- a/libc/bionic/pthread_attr.cpp
+++ b/libc/bionic/pthread_attr.cpp
@@ -30,16 +30,10 @@
#include "pthread_internal.h"
-// Traditionally we give threads a 1MiB stack. When we started allocating per-thread
-// alternate signal stacks to ease debugging of stack overflows, we subtracted the
-// same amount we were using there from the default thread stack size. This should
-// keep memory usage roughly constant.
-#define DEFAULT_THREAD_STACK_SIZE ((1 * 1024 * 1024) - SIGSTKSZ)
-
int pthread_attr_init(pthread_attr_t* attr) {
attr->flags = 0;
attr->stack_base = NULL;
- attr->stack_size = DEFAULT_THREAD_STACK_SIZE;
+ attr->stack_size = PTHREAD_STACK_SIZE_DEFAULT;
attr->guard_size = PAGE_SIZE;
attr->sched_policy = SCHED_NORMAL;
attr->sched_priority = 0;
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index 31b8ca7..6fe2a98 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -77,6 +77,15 @@
/* Has the thread already exited but not been joined? */
#define PTHREAD_ATTR_FLAG_ZOMBIE 0x00000008
+/*
+ * Traditionally we give threads a 1MiB stack. When we started
+ * allocating per-thread alternate signal stacks to ease debugging of
+ * stack overflows, we subtracted the same amount we were using there
+ * from the default thread stack size. This should keep memory usage
+ * roughly constant.
+ */
+#define PTHREAD_STACK_SIZE_DEFAULT ((1 * 1024 * 1024) - SIGSTKSZ)
+
__LIBC_HIDDEN__ extern pthread_internal_t* gThreadList;
__LIBC_HIDDEN__ extern pthread_mutex_t gThreadListLock;
diff --git a/libc/bionic/stubs.cpp b/libc/bionic/stubs.cpp
index e8411b7..56f5c045 100644
--- a/libc/bionic/stubs.cpp
+++ b/libc/bionic/stubs.cpp
@@ -469,3 +469,15 @@
void endusershell() {
UNIMPLEMENTED;
}
+
+// Portable code should use sysconf(_SC_PAGESIZE) directly instead.
+int getpagesize() {
+ return sysconf(_SC_PAGESIZE);
+}
+
+// These were accidentally declared in <unistd.h> because we stupidly used to inline
+// getpagesize() and __getpageshift(). Needed for backwards compatibility with old NDK apps.
+extern "C" {
+ unsigned int __page_size = PAGE_SIZE;
+ unsigned int __page_shift = PAGE_SHIFT;
+}
diff --git a/libc/bionic/system_properties.c b/libc/bionic/system_properties.c
index 4c2e5a2..fd56431 100644
--- a/libc/bionic/system_properties.c
+++ b/libc/bionic/system_properties.c
@@ -325,6 +325,8 @@
{
if (off > pa_data_size)
return NULL;
+ if (!__system_property_area__)
+ return NULL;
return __system_property_area__->data + off;
}
@@ -384,6 +386,8 @@
{
const char *remaining_name = name;
+ if (!trie) return NULL;
+
while (true) {
char *sep = strchr(remaining_name, '.');
bool want_subtree = (sep != NULL);
diff --git a/libc/include/link.h b/libc/include/link.h
index 842b448..0edf5df 100644
--- a/libc/include/link.h
+++ b/libc/include/link.h
@@ -43,11 +43,11 @@
ElfW(Half) dlpi_phnum;
};
+int dl_iterate_phdr(int (*cb)(struct dl_phdr_info*, size_t, void*), void*);
+
#ifdef __arm__
typedef long unsigned int* _Unwind_Ptr;
_Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc, int* pcount);
-#else
-int dl_iterate_phdr(int (*cb)(struct dl_phdr_info*, size_t, void*), void*);
#endif
__END_DECLS
diff --git a/libc/include/string.h b/libc/include/string.h
index f6b4acf..10ff722 100644
--- a/libc/include/string.h
+++ b/libc/include/string.h
@@ -46,6 +46,8 @@
extern char* index(const char *, int) __purefunc;
extern char* strchr(const char *, int) __purefunc;
+extern char* __strchr_chk(const char *, int, size_t);
+
extern char* strrchr(const char *, int) __purefunc;
extern size_t strlen(const char *) __purefunc;
@@ -238,8 +240,6 @@
return __strlen_chk(s, bos);
}
-extern char* __strchr_chk(const char *, int, size_t);
-
__BIONIC_FORTIFY_INLINE
char* strchr(const char *s, int c) {
size_t bos = __bos(s);
diff --git a/libc/include/sys/mman.h b/libc/include/sys/mman.h
index 7a32974..7c5f8d7 100644
--- a/libc/include/sys/mman.h
+++ b/libc/include/sys/mman.h
@@ -45,6 +45,7 @@
#define MREMAP_FIXED 2
extern void* mmap(void *, size_t, int, int, int, off_t);
+extern void* mmap64(void *, size_t, int, int, int, off64_t);
extern int munmap(void *, size_t);
extern int msync(const void *, size_t, int);
extern int mprotect(const void *, size_t, int);
diff --git a/libc/include/sys/sendfile.h b/libc/include/sys/sendfile.h
index d5aba26..81a3c44 100644
--- a/libc/include/sys/sendfile.h
+++ b/libc/include/sys/sendfile.h
@@ -25,6 +25,7 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
+
#ifndef _SYS_SENDFILE_H_
#define _SYS_SENDFILE_H_
@@ -33,7 +34,8 @@
__BEGIN_DECLS
-extern ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
+extern ssize_t sendfile(int out_fd, int in_fd, off_t* offset, size_t count);
+extern ssize_t sendfile64(int out_fd, int in_fd, off64_t* offset, size_t count);
__END_DECLS
diff --git a/libc/include/sys/types.h b/libc/include/sys/types.h
index a0ce405..8b7fea8 100644
--- a/libc/include/sys/types.h
+++ b/libc/include/sys/types.h
@@ -65,7 +65,7 @@
typedef __kernel_off_t off_t;
#endif
typedef __kernel_loff_t loff_t;
-typedef loff_t off64_t; /* GLibc-specific */
+typedef loff_t off64_t;
typedef __kernel_pid_t pid_t;
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index 98970ae..60964f0 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -122,6 +122,7 @@
extern int fchown(int, uid_t, gid_t);
extern int lchown(const char *, uid_t, gid_t);
extern int truncate(const char *, off_t);
+extern int truncate64(const char *, off64_t);
extern char *getcwd(char *, size_t);
extern int sync(void);
@@ -170,14 +171,7 @@
extern int acct(const char* filepath);
-static __inline__ int getpagesize(void) {
- extern unsigned int __page_size;
- return __page_size;
-}
-static __inline__ int __getpageshift(void) {
- extern unsigned int __page_shift;
- return __page_shift;
-}
+int getpagesize(void);
extern int sysconf(int name);
diff --git a/libc/kernel/common/linux/netlink.h b/libc/kernel/common/linux/netlink.h
index b700086..45df44f 100644
--- a/libc/kernel/common/linux/netlink.h
+++ b/libc/kernel/common/linux/netlink.h
@@ -18,117 +18,153 @@
****************************************************************************/
#ifndef __LINUX_NETLINK_H
#define __LINUX_NETLINK_H
+#include <linux/kernel.h>
#include <linux/socket.h>
-#include <linux/types.h>
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#include <linux/types.h>
#define NETLINK_ROUTE 0
#define NETLINK_UNUSED 1
#define NETLINK_USERSOCK 2
-#define NETLINK_FIREWALL 3
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define NETLINK_INET_DIAG 4
+#define NETLINK_FIREWALL 3
+#define NETLINK_SOCK_DIAG 4
#define NETLINK_NFLOG 5
#define NETLINK_XFRM 6
-#define NETLINK_SELINUX 7
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define NETLINK_SELINUX 7
#define NETLINK_ISCSI 8
#define NETLINK_AUDIT 9
#define NETLINK_FIB_LOOKUP 10
-#define NETLINK_CONNECTOR 11
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define NETLINK_CONNECTOR 11
#define NETLINK_NETFILTER 12
#define NETLINK_IP6_FW 13
#define NETLINK_DNRTMSG 14
-#define NETLINK_KOBJECT_UEVENT 15
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define NETLINK_KOBJECT_UEVENT 15
#define NETLINK_GENERIC 16
#define NETLINK_SCSITRANSPORT 18
#define NETLINK_ECRYPTFS 19
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define NETLINK_RDMA 20
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define NETLINK_IDLETIMER 21
+#define NETLINK_CRYPTO 21
+#define NETLINK_INET_DIAG NETLINK_SOCK_DIAG
#define MAX_LINKS 32
-struct sockaddr_nl {
- sa_family_t nl_family;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+struct sockaddr_nl {
+ __kernel_sa_family_t nl_family;
unsigned short nl_pad;
__u32 nl_pid;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
__u32 nl_groups;
};
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
struct nlmsghdr {
__u32 nlmsg_len;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
__u16 nlmsg_type;
__u16 nlmsg_flags;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
__u32 nlmsg_seq;
__u32 nlmsg_pid;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
};
#define NLM_F_REQUEST 1
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define NLM_F_MULTI 2
#define NLM_F_ACK 4
-#define NLM_F_ECHO 8
-#define NLM_F_ROOT 0x100
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define NLM_F_ECHO 8
+#define NLM_F_DUMP_INTR 16
+#define NLM_F_ROOT 0x100
#define NLM_F_MATCH 0x200
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define NLM_F_ATOMIC 0x400
#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH)
#define NLM_F_REPLACE 0x100
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define NLM_F_EXCL 0x200
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define NLM_F_CREATE 0x400
#define NLM_F_APPEND 0x800
#define NLMSG_ALIGNTO 4U
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) )
-#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
-#define NLMSG_LENGTH(len) ((len)+NLMSG_ALIGN(NLMSG_HDRLEN))
-#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
+#define NLMSG_LENGTH(len) ((len) + NLMSG_HDRLEN)
+#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
#define NLMSG_DATA(nlh) ((void*)(((char*)nlh) + NLMSG_LENGTH(0)))
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), (struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
#define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && (nlh)->nlmsg_len <= (len))
#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len)))
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define NLMSG_NOOP 0x1
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define NLMSG_ERROR 0x2
#define NLMSG_DONE 0x3
#define NLMSG_OVERRUN 0x4
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define NLMSG_MIN_TYPE 0x10
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
struct nlmsgerr {
int error;
struct nlmsghdr msg;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
};
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define NETLINK_ADD_MEMBERSHIP 1
#define NETLINK_DROP_MEMBERSHIP 2
#define NETLINK_PKTINFO 3
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define NETLINK_BROADCAST_ERROR 4
-#define NETLINK_NO_ENOBUFS 5
-struct nl_pktinfo {
- __u32 group;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define NETLINK_NO_ENOBUFS 5
+#define NETLINK_RX_RING 6
+#define NETLINK_TX_RING 7
+struct nl_pktinfo {
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 group;
};
+struct nl_mmap_req {
+ unsigned int nm_block_size;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ unsigned int nm_block_nr;
+ unsigned int nm_frame_size;
+ unsigned int nm_frame_nr;
+};
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+struct nl_mmap_hdr {
+ unsigned int nm_status;
+ unsigned int nm_len;
+ __u32 nm_group;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 nm_pid;
+ __u32 nm_uid;
+ __u32 nm_gid;
+};
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+enum nl_mmap_status {
+ NL_MMAP_STATUS_UNUSED,
+ NL_MMAP_STATUS_RESERVED,
+ NL_MMAP_STATUS_VALID,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ NL_MMAP_STATUS_COPY,
+ NL_MMAP_STATUS_SKIP,
+};
+#define NL_MMAP_MSG_ALIGNMENT NLMSG_ALIGNTO
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define NL_MMAP_MSG_ALIGN(sz) __ALIGN_KERNEL(sz, NL_MMAP_MSG_ALIGNMENT)
+#define NL_MMAP_HDRLEN NL_MMAP_MSG_ALIGN(sizeof(struct nl_mmap_hdr))
#define NET_MAJOR 36
enum {
- NETLINK_UNCONNECTED = 0,
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ NETLINK_UNCONNECTED = 0,
NETLINK_CONNECTED,
};
struct nlattr {
- __u16 nla_len;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u16 nla_len;
__u16 nla_type;
};
#define NLA_F_NESTED (1 << 15)
-#define NLA_F_NET_BYTEORDER (1 << 14)
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define NLA_F_NET_BYTEORDER (1 << 14)
#define NLA_TYPE_MASK ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER)
#define NLA_ALIGNTO 4
#define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1))
-#define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr)))
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr)))
#endif
diff --git a/libc/kernel/common/linux/sock_diag.h b/libc/kernel/common/linux/sock_diag.h
new file mode 100644
index 0000000..0dc2902
--- /dev/null
+++ b/libc/kernel/common/linux/sock_diag.h
@@ -0,0 +1,43 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI__SOCK_DIAG_H__
+#define _UAPI__SOCK_DIAG_H__
+#include <linux/types.h>
+#define SOCK_DIAG_BY_FAMILY 20
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+struct sock_diag_req {
+ __u8 sdiag_family;
+ __u8 sdiag_protocol;
+};
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+enum {
+ SK_MEMINFO_RMEM_ALLOC,
+ SK_MEMINFO_RCVBUF,
+ SK_MEMINFO_WMEM_ALLOC,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ SK_MEMINFO_SNDBUF,
+ SK_MEMINFO_FWD_ALLOC,
+ SK_MEMINFO_WMEM_QUEUED,
+ SK_MEMINFO_OPTMEM,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ SK_MEMINFO_BACKLOG,
+ SK_MEMINFO_VARS,
+};
+#endif
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
diff --git a/libc/kernel/common/linux/taskstats.h b/libc/kernel/common/linux/taskstats.h
index 0e1cb67..fd7e9ed 100644
--- a/libc/kernel/common/linux/taskstats.h
+++ b/libc/kernel/common/linux/taskstats.h
@@ -18,12 +18,17 @@
****************************************************************************/
#ifndef _LINUX_TASKSTATS_H
#define _LINUX_TASKSTATS_H
-#define TASKSTATS_VERSION 1
-struct taskstats {
+#include <linux/types.h>
+#define TASKSTATS_VERSION 8
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define TS_COMM_LEN 32
+struct taskstats {
__u16 version;
- __u16 padding[3];
- __u64 cpu_count;
+ __u32 ac_exitcode;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u8 ac_flag;
+ __u8 ac_nice;
+ __u64 cpu_count __attribute__((aligned(8)));
__u64 cpu_delay_total;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
__u64 blkio_count;
@@ -33,6 +38,46 @@
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
__u64 cpu_run_real_total;
__u64 cpu_run_virtual_total;
+ char ac_comm[TS_COMM_LEN];
+ __u8 ac_sched __attribute__((aligned(8)));
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u8 ac_pad[3];
+ __u32 ac_uid __attribute__((aligned(8)));
+ __u32 ac_gid;
+ __u32 ac_pid;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 ac_ppid;
+ __u32 ac_btime;
+ __u64 ac_etime __attribute__((aligned(8)));
+ __u64 ac_utime;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u64 ac_stime;
+ __u64 ac_minflt;
+ __u64 ac_majflt;
+ __u64 coremem;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u64 virtmem;
+ __u64 hiwater_rss;
+ __u64 hiwater_vm;
+ __u64 read_char;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u64 write_char;
+ __u64 read_syscalls;
+ __u64 write_syscalls;
+#define TASKSTATS_HAS_IO_ACCOUNTING
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u64 read_bytes;
+ __u64 write_bytes;
+ __u64 cancelled_write_bytes;
+ __u64 nvcsw;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u64 nivcsw;
+ __u64 ac_utimescaled;
+ __u64 ac_stimescaled;
+ __u64 cpu_scaled_run_real_total;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u64 freepages_count;
+ __u64 freepages_delay_total;
};
enum {
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
@@ -52,22 +97,23 @@
TASKSTATS_TYPE_AGGR_PID,
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
TASKSTATS_TYPE_AGGR_TGID,
+ TASKSTATS_TYPE_NULL,
__TASKSTATS_TYPE_MAX,
};
-#define TASKSTATS_TYPE_MAX (__TASKSTATS_TYPE_MAX - 1)
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define TASKSTATS_TYPE_MAX (__TASKSTATS_TYPE_MAX - 1)
enum {
TASKSTATS_CMD_ATTR_UNSPEC = 0,
TASKSTATS_CMD_ATTR_PID,
- TASKSTATS_CMD_ATTR_TGID,
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ TASKSTATS_CMD_ATTR_TGID,
TASKSTATS_CMD_ATTR_REGISTER_CPUMASK,
TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK,
__TASKSTATS_CMD_ATTR_MAX,
-};
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+};
#define TASKSTATS_CMD_ATTR_MAX (__TASKSTATS_CMD_ATTR_MAX - 1)
#define TASKSTATS_GENL_NAME "TASKSTATS"
#define TASKSTATS_GENL_VERSION 0x1
-#endif
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#endif
diff --git a/libc/private/bionic_tls.h b/libc/private/bionic_tls.h
index d15b1ca..9ea3647 100644
--- a/libc/private/bionic_tls.h
+++ b/libc/private/bionic_tls.h
@@ -113,7 +113,7 @@
__END_DECLS
#if defined(__cplusplus)
-struct KernelArgumentBlock;
+class KernelArgumentBlock;
extern __LIBC_HIDDEN__ void __libc_init_tls(KernelArgumentBlock& args);
#endif
diff --git a/libc/stdio/local.h b/libc/stdio/local.h
index e3a40bc..a175d6f 100644
--- a/libc/stdio/local.h
+++ b/libc/stdio/local.h
@@ -93,3 +93,5 @@
#define FLOCKFILE(fp) do { if (__isthreaded) flockfile(fp); } while (0)
#define FUNLOCKFILE(fp) do { if (__isthreaded) funlockfile(fp); } while (0)
+
+#define FLOATING_POINT
diff --git a/libc/stdio/vfprintf.c b/libc/stdio/vfprintf.c
index 646b6b1..b101145 100644
--- a/libc/stdio/vfprintf.c
+++ b/libc/stdio/vfprintf.c
@@ -451,7 +451,12 @@
goto rflag;
#endif
case 'h':
- flags |= SHORTINT;
+ if (*fmt == 'h') {
+ fmt++;
+ flags |= CHARINT;
+ } else {
+ flags |= SHORTINT;
+ }
goto rflag;
case 'j':
flags |= MAXINT;
diff --git a/libc/tools/bionic_utils.py b/libc/tools/bionic_utils.py
index dccf9e3..baa41be 100644
--- a/libc/tools/bionic_utils.py
+++ b/libc/tools/bionic_utils.py
@@ -51,7 +51,7 @@
""" parse a syscall spec line.
line processing, format is
- return type func_name[:syscall_name[:call_id]] ( [paramlist] ) (syscall_number[,syscall_number_x86])|stub
+ return type func_name[:syscall_name[:call_id]] ( [paramlist] ) architecture_list
"""
pos_lparen = line.find('(')
E = self.E
@@ -102,34 +102,27 @@
syscall_params = []
params = "void"
- number = line[pos_rparen+1:].strip()
- if number == "stub":
- syscall_common = -1
- syscall_arm = -1
- syscall_x86 = -1
- syscall_mips = -1
+ # Parse the architecture list.
+ syscall_common = -1
+ syscall_arm = -1
+ syscall_x86 = -1
+ syscall_mips = -1
+ arch_list = line[pos_rparen+1:].strip()
+ if arch_list == "custom":
+ pass
+ elif arch_list == "all":
+ syscall_common = 1
else:
- try:
- if number[0] == '#':
- number = number[1:].strip()
- numbers = string.split(number,',')
- if len(numbers) == 1:
- syscall_common = int(numbers[0])
- syscall_arm = -1
- syscall_x86 = -1
- syscall_mips = -1
+ for arch in string.split(arch_list, ','):
+ if arch == "arm":
+ syscall_arm = 1
+ elif arch == "x86":
+ syscall_x86 = 1
+ elif arch == "mips":
+ syscall_mips = 1
else:
- if len(numbers) == 3:
- syscall_common = -1
- syscall_arm = int(numbers[0])
- syscall_x86 = int(numbers[1])
- syscall_mips = int(numbers[2])
- else:
- E("invalid syscall number format in '%s'" % line)
- return
- except:
- E("invalid syscall number in '%s'" % line)
- return
+ E("invalid syscall architecture list in '%s'" % line)
+ return
global verbose
if verbose >= 2:
diff --git a/libc/tzcode/localtime.c b/libc/tzcode/localtime.c
index b23eca4..f374541 100644
--- a/libc/tzcode/localtime.c
+++ b/libc/tzcode/localtime.c
@@ -2114,7 +2114,15 @@
return (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
}
-static int __bionic_open_tzdata_path(const char* path, const char* olson_id, int* data_size) {
+static int __bionic_open_tzdata_path(const char* path_prefix_variable, const char* path_suffix,
+ const char* olson_id, int* data_size) {
+ const char* path_prefix = getenv(path_prefix_variable);
+ if (path_prefix == NULL) {
+ fprintf(stderr, "%s: %s not set!\n", __FUNCTION__, path_prefix_variable);
+ return -1;
+ }
+ char path[PATH_MAX];
+ snprintf(path, sizeof(path), "%s/%s", path_prefix, path_suffix);
int fd = TEMP_FAILURE_RETRY(open(path, OPEN_MODE));
if (fd == -1) {
XLOG(("%s: could not open \"%s\": %s\n", __FUNCTION__, path, strerror(errno)));
@@ -2202,10 +2210,9 @@
}
static int __bionic_open_tzdata(const char* olson_id, int* data_size) {
- // TODO: use $ANDROID_DATA and $ANDROID_ROOT like libcore, to support bionic on the host.
- int fd = __bionic_open_tzdata_path("/data/misc/zoneinfo/tzdata", olson_id, data_size);
+ int fd = __bionic_open_tzdata_path("ANDROID_DATA", "/misc/zoneinfo/tzdata", olson_id, data_size);
if (fd < 0) {
- fd = __bionic_open_tzdata_path("/system/usr/share/zoneinfo/tzdata", olson_id, data_size);
+ fd = __bionic_open_tzdata_path("ANDROID_ROOT", "/usr/share/zoneinfo/tzdata", olson_id, data_size);
if (fd == -2) {
// The first thing that 'recovery' does is try to format the current time. It doesn't have
// any tzdata available, so we must not abort here --- doing so breaks the recovery image!
diff --git a/libdl/libdl.c b/libdl/libdl.c
index 378f521..548364c 100644
--- a/libdl/libdl.c
+++ b/libdl/libdl.c
@@ -30,12 +30,8 @@
void *dl_unwind_find_exidx(void *pc, int *pcount) { return 0; }
-#elif defined(__i386__) || defined(__mips__)
+#endif
/* we munge the cb definition so we don't have to include any headers here.
* It won't affect anything since these are just symbols anyway */
int dl_iterate_phdr(int (*cb)(void *info, void *size, void *data), void *data) { return 0; }
-
-#else
-#error Unsupported architecture. Only mips, arm and x86 are supported.
-#endif
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index 638164d..946f79e 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -146,11 +146,10 @@
}
#if defined(ANDROID_ARM_LINKER)
-// 0000000 00011111 111112 22222222 2333333 3333444444444455555555556666666 6667
-// 0123456 78901234 567890 12345678 9012345 6789012345678901234567890123456 7890
+// 0000000 00011111 111112 22222222 2333333 3333444444444455555555556666666 6667777777777888 8888888
+// 0123456 78901234 567890 12345678 9012345 6789012345678901234567890123456 7890123456789012 3456789
#define ANDROID_LIBDL_STRTAB \
- "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0android_update_LD_LIBRARY_PATH\0dl_unwind_find_exidx\0"
-
+ "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0android_update_LD_LIBRARY_PATH\0dl_iterate_phdr\0dl_unwind_find_exidx\0"
#elif defined(ANDROID_X86_LINKER) || defined(ANDROID_MIPS_LINKER)
// 0000000 00011111 111112 22222222 2333333 3333444444444455555555556666666 6667
// 0123456 78901234 567890 12345678 9012345 6789012345678901234567890123456 7890
@@ -181,10 +180,9 @@
ELF32_SYM_INITIALIZER(21, &dlerror, 1),
ELF32_SYM_INITIALIZER(29, &dladdr, 1),
ELF32_SYM_INITIALIZER(36, &android_update_LD_LIBRARY_PATH, 1),
-#if defined(ANDROID_ARM_LINKER)
- ELF32_SYM_INITIALIZER(67, &dl_unwind_find_exidx, 1),
-#elif defined(ANDROID_X86_LINKER) || defined(ANDROID_MIPS_LINKER)
ELF32_SYM_INITIALIZER(67, &dl_iterate_phdr, 1),
+#if defined(ANDROID_ARM_LINKER)
+ ELF32_SYM_INITIALIZER(83, &dl_unwind_find_exidx, 1),
#endif
};
@@ -207,7 +205,11 @@
// Note that adding any new symbols here requires
// stubbing them out in libdl.
static unsigned gLibDlBuckets[1] = { 1 };
+#if defined(ANDROID_ARM_LINKER)
+static unsigned gLibDlChains[9] = { 0, 2, 3, 4, 5, 6, 7, 8, 0 };
+#else
static unsigned gLibDlChains[8] = { 0, 2, 3, 4, 5, 6, 7, 0 };
+#endif
// This is used by the dynamic linker. Every process gets these symbols for free.
soinfo libdl_info = {
@@ -223,8 +225,8 @@
strtab: ANDROID_LIBDL_STRTAB,
symtab: gLibDlSymtab,
- nbucket: 1,
- nchain: 8,
+ nbucket: sizeof(gLibDlBuckets)/sizeof(unsigned),
+ nchain: sizeof(gLibDlChains)/sizeof(unsigned),
bucket: gLibDlBuckets,
chain: gLibDlChains,
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 623be29..0f20181 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -414,7 +414,7 @@
return NULL;
}
-#elif defined(ANDROID_X86_LINKER) || defined(ANDROID_MIPS_LINKER)
+#endif
/* Here, we only have to provide a callback to iterate across all the
* loaded libraries. gcc_eh does the rest. */
@@ -437,8 +437,6 @@
return rv;
}
-#endif
-
static Elf32_Sym* soinfo_elf_lookup(soinfo* si, unsigned hash, const char* name) {
Elf32_Sym* symtab = si->symtab;
const char* strtab = si->strtab;
diff --git a/tests/Android.mk b/tests/Android.mk
index 534aa30..e60b908 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -80,6 +80,7 @@
string_test.cpp \
strings_test.cpp \
stubs_test.cpp \
+ sys_sendfile_test.cpp \
sys_stat_test.cpp \
system_properties_test.cpp \
time_test.cpp \
@@ -188,6 +189,28 @@
endif
# -----------------------------------------------------------------------------
+# Run the unit tests built against x86 bionic on an x86 host.
+# -----------------------------------------------------------------------------
+
+ifeq ($(HOST_OS)-$(HOST_ARCH),linux-x86)
+ifeq ($(TARGET_ARCH),x86)
+# gtest needs EXTERNAL_STORAGE for death test output.
+# bionic itself should always work relative to ANDROID_DATA or ANDROID_ROOT.
+# We create /data/local/tmp to be as much like the regular target environment
+# as possible.
+bionic-unit-tests-run-on-host: bionic-unit-tests $(TARGET_OUT_EXECUTABLES)/linker
+ mkdir -p $(TARGET_OUT_DATA)/local/tmp
+ cp $(TARGET_OUT_EXECUTABLES)/linker /system/bin
+ cp $(TARGET_OUT_EXECUTABLES)/sh /system/bin
+ ANDROID_DATA=$(TARGET_OUT_DATA) \
+ ANDROID_ROOT=$(TARGET_OUT) \
+ EXTERNAL_STORAGE=$(TARGET_OUT_DATA)/local/tmp \
+ LD_LIBRARY_PATH=$(TARGET_OUT_SHARED_LIBRARIES) \
+ $(TARGET_OUT_DATA_NATIVE_TESTS)/bionic-unit-tests/bionic-unit-tests
+endif
+endif
+
+# -----------------------------------------------------------------------------
# FORTIFY_SOURCE tests
# -----------------------------------------------------------------------------
diff --git a/tests/TemporaryFile.h b/tests/TemporaryFile.h
new file mode 100644
index 0000000..878fb13
--- /dev/null
+++ b/tests/TemporaryFile.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <unistd.h>
+
+class TemporaryFile {
+ public:
+ TemporaryFile() {
+#if __BIONIC__
+ const char* tmp_dir = "/data/local/tmp";
+#else
+ const char* tmp_dir = "/tmp";
+#endif
+ snprintf(filename, sizeof(filename), "%s/TemporaryFile-XXXXXX", tmp_dir);
+ fd = mkstemp(filename);
+ }
+
+ ~TemporaryFile() {
+ close(fd);
+ unlink(filename);
+ }
+
+ int fd;
+ char filename[1024];
+};
diff --git a/tests/fortify_test.cpp b/tests/fortify_test.cpp
index aa13736..5ec15b8 100644
--- a/tests/fortify_test.cpp
+++ b/tests/fortify_test.cpp
@@ -717,3 +717,58 @@
ASSERT_EQ('\0', dst[13]);
ASSERT_EQ('\0', dst[14]);
}
+
+TEST(TEST_NAME, strcat_chk_max_int_size) {
+ char buf[10];
+ memset(buf, 'A', sizeof(buf));
+ buf[0] = 'a';
+ buf[1] = '\0';
+ char* res = __strcat_chk(buf, "01234567", (size_t)-1);
+ ASSERT_EQ(buf, res);
+ ASSERT_EQ('a', buf[0]);
+ ASSERT_EQ('0', buf[1]);
+ ASSERT_EQ('1', buf[2]);
+ ASSERT_EQ('2', buf[3]);
+ ASSERT_EQ('3', buf[4]);
+ ASSERT_EQ('4', buf[5]);
+ ASSERT_EQ('5', buf[6]);
+ ASSERT_EQ('6', buf[7]);
+ ASSERT_EQ('7', buf[8]);
+ ASSERT_EQ('\0', buf[9]);
+}
+
+extern "C" char* __strcpy_chk(char*, const char*, size_t);
+
+TEST(TEST_NAME, strcpy_chk_max_int_size) {
+ char buf[10];
+ char* res = __strcpy_chk(buf, "012345678", (size_t)-1);
+ ASSERT_EQ(buf, res);
+ ASSERT_EQ('0', buf[0]);
+ ASSERT_EQ('1', buf[1]);
+ ASSERT_EQ('2', buf[2]);
+ ASSERT_EQ('3', buf[3]);
+ ASSERT_EQ('4', buf[4]);
+ ASSERT_EQ('5', buf[5]);
+ ASSERT_EQ('6', buf[6]);
+ ASSERT_EQ('7', buf[7]);
+ ASSERT_EQ('8', buf[8]);
+ ASSERT_EQ('\0', buf[9]);
+}
+
+extern "C" void* __memcpy_chk(void*, const void*, size_t, size_t);
+
+TEST(TEST_NAME, memcpy_chk_max_int_size) {
+ char buf[10];
+ void* res = __memcpy_chk(buf, "012345678", sizeof(buf), (size_t)-1);
+ ASSERT_EQ((void*)buf, res);
+ ASSERT_EQ('0', buf[0]);
+ ASSERT_EQ('1', buf[1]);
+ ASSERT_EQ('2', buf[2]);
+ ASSERT_EQ('3', buf[3]);
+ ASSERT_EQ('4', buf[4]);
+ ASSERT_EQ('5', buf[5]);
+ ASSERT_EQ('6', buf[6]);
+ ASSERT_EQ('7', buf[7]);
+ ASSERT_EQ('8', buf[8]);
+ ASSERT_EQ('\0', buf[9]);
+}
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index 2e779d8..18fa64a 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -17,6 +17,7 @@
#include <gtest/gtest.h>
#include <errno.h>
+#include <limits.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -182,6 +183,132 @@
snprintf(buf, sizeof(buf), "%zd", v);
}
+TEST(stdio, snprintf_smoke) {
+ char buf[BUFSIZ];
+
+ snprintf(buf, sizeof(buf), "a");
+ EXPECT_STREQ("a", buf);
+
+ snprintf(buf, sizeof(buf), "%%");
+ EXPECT_STREQ("%", buf);
+
+ snprintf(buf, sizeof(buf), "01234");
+ EXPECT_STREQ("01234", buf);
+
+ snprintf(buf, sizeof(buf), "a%sb", "01234");
+ EXPECT_STREQ("a01234b", buf);
+
+ char* s = NULL;
+ snprintf(buf, sizeof(buf), "a%sb", s);
+ EXPECT_STREQ("a(null)b", buf);
+
+ snprintf(buf, sizeof(buf), "aa%scc", "bb");
+ EXPECT_STREQ("aabbcc", buf);
+
+ snprintf(buf, sizeof(buf), "a%cc", 'b');
+ EXPECT_STREQ("abc", buf);
+
+ snprintf(buf, sizeof(buf), "a%db", 1234);
+ EXPECT_STREQ("a1234b", buf);
+
+ snprintf(buf, sizeof(buf), "a%db", -8123);
+ EXPECT_STREQ("a-8123b", buf);
+
+ snprintf(buf, sizeof(buf), "a%hdb", 0x7fff0010);
+ EXPECT_STREQ("a16b", buf);
+
+ snprintf(buf, sizeof(buf), "a%hhdb", 0x7fffff10);
+ EXPECT_STREQ("a16b", buf);
+
+ snprintf(buf, sizeof(buf), "a%lldb", 0x1000000000LL);
+ EXPECT_STREQ("a68719476736b", buf);
+
+ snprintf(buf, sizeof(buf), "a%ldb", 70000L);
+ EXPECT_STREQ("a70000b", buf);
+
+ snprintf(buf, sizeof(buf), "a%pb", reinterpret_cast<void*>(0xb0001234));
+ EXPECT_STREQ("a0xb0001234b", buf);
+
+ snprintf(buf, sizeof(buf), "a%xz", 0x12ab);
+ EXPECT_STREQ("a12abz", buf);
+
+ snprintf(buf, sizeof(buf), "a%Xz", 0x12ab);
+ EXPECT_STREQ("a12ABz", buf);
+
+ snprintf(buf, sizeof(buf), "a%08xz", 0x123456);
+ EXPECT_STREQ("a00123456z", buf);
+
+ snprintf(buf, sizeof(buf), "a%5dz", 1234);
+ EXPECT_STREQ("a 1234z", buf);
+
+ snprintf(buf, sizeof(buf), "a%05dz", 1234);
+ EXPECT_STREQ("a01234z", buf);
+
+ snprintf(buf, sizeof(buf), "a%8dz", 1234);
+ EXPECT_STREQ("a 1234z", buf);
+
+ snprintf(buf, sizeof(buf), "a%-8dz", 1234);
+ EXPECT_STREQ("a1234 z", buf);
+
+ snprintf(buf, sizeof(buf), "A%-11sZ", "abcdef");
+ EXPECT_STREQ("Aabcdef Z", buf);
+
+ snprintf(buf, sizeof(buf), "A%s:%dZ", "hello", 1234);
+ EXPECT_STREQ("Ahello:1234Z", buf);
+
+ snprintf(buf, sizeof(buf), "a%03d:%d:%02dz", 5, 5, 5);
+ EXPECT_STREQ("a005:5:05z", buf);
+
+ void* p = NULL;
+ snprintf(buf, sizeof(buf), "a%d,%pz", 5, p);
+ EXPECT_STREQ("a5,0x0z", buf);
+
+ snprintf(buf, sizeof(buf), "a%lld,%d,%d,%dz", 0x1000000000LL, 6, 7, 8);
+ EXPECT_STREQ("a68719476736,6,7,8z", buf);
+
+ snprintf(buf, sizeof(buf), "a_%f_b", 1.23f);
+ EXPECT_STREQ("a_1.230000_b", buf);
+
+ snprintf(buf, sizeof(buf), "a_%g_b", 3.14d);
+ EXPECT_STREQ("a_3.14_b", buf);
+}
+
+TEST(stdio, snprintf_d_INT_MAX) {
+ char buf[BUFSIZ];
+ snprintf(buf, sizeof(buf), "%d", INT_MAX);
+ EXPECT_STREQ("2147483647", buf);
+}
+
+TEST(stdio, snprintf_d_INT_MIN) {
+ char buf[BUFSIZ];
+ snprintf(buf, sizeof(buf), "%d", INT_MIN);
+ EXPECT_STREQ("-2147483648", buf);
+}
+
+TEST(stdio, snprintf_ld_LONG_MAX) {
+ char buf[BUFSIZ];
+ snprintf(buf, sizeof(buf), "%ld", LONG_MAX);
+ EXPECT_STREQ("2147483647", buf);
+}
+
+TEST(stdio, snprintf_ld_LONG_MIN) {
+ char buf[BUFSIZ];
+ snprintf(buf, sizeof(buf), "%ld", LONG_MIN);
+ EXPECT_STREQ("-2147483648", buf);
+}
+
+TEST(stdio, snprintf_lld_LLONG_MAX) {
+ char buf[BUFSIZ];
+ snprintf(buf, sizeof(buf), "%lld", LLONG_MAX);
+ EXPECT_STREQ("9223372036854775807", buf);
+}
+
+TEST(stdio, snprintf_lld_LLONG_MIN) {
+ char buf[BUFSIZ];
+ snprintf(buf, sizeof(buf), "%lld", LLONG_MIN);
+ EXPECT_STREQ("-9223372036854775808", buf);
+}
+
TEST(stdio, popen) {
FILE* fp = popen("cat /proc/version", "r");
ASSERT_TRUE(fp != NULL);
diff --git a/tests/sys_sendfile_test.cpp b/tests/sys_sendfile_test.cpp
new file mode 100644
index 0000000..bf23d3d
--- /dev/null
+++ b/tests/sys_sendfile_test.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include "TemporaryFile.h"
+
+#include <sys/sendfile.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+TEST(sys_sendfile, sendfile) {
+ TemporaryFile src_file;
+ ASSERT_EQ(5, TEMP_FAILURE_RETRY(write(src_file.fd, "hello", 5)));
+
+ TemporaryFile dst_file;
+
+ off_t offset = 2;
+ size_t count = 2;
+ ssize_t rc = sendfile(dst_file.fd, src_file.fd, &offset, count);
+ ASSERT_EQ(2, rc);
+ ASSERT_EQ(4, offset);
+
+ ASSERT_EQ(0, lseek(dst_file.fd, 0, SEEK_SET));
+ char buf[3];
+ buf[2] = '\0';
+ ASSERT_EQ(2, TEMP_FAILURE_RETRY(read(dst_file.fd, &buf, 2)));
+ ASSERT_STREQ("ll", buf);
+}
+
+#if __BIONIC__
+TEST(sys_sendfile, sendfile64) {
+ TemporaryFile src_file;
+ ASSERT_EQ(5, TEMP_FAILURE_RETRY(write(src_file.fd, "hello", 5)));
+
+ TemporaryFile dst_file;
+
+ off64_t offset = 2;
+ size_t count = 2;
+ ssize_t rc = sendfile64(dst_file.fd, src_file.fd, &offset, count);
+ ASSERT_EQ(2, rc);
+ ASSERT_EQ(4, offset);
+
+ ASSERT_EQ(0, lseek(dst_file.fd, 0, SEEK_SET));
+ char buf[3];
+ buf[2] = '\0';
+ ASSERT_EQ(2, TEMP_FAILURE_RETRY(read(dst_file.fd, &buf, 2)));
+ ASSERT_STREQ("ll", buf);
+}
+#endif
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 3ccaf3b..3193083 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -15,6 +15,7 @@
*/
#include <gtest/gtest.h>
+#include "TemporaryFile.h"
#include <stdint.h>
#include <unistd.h>
@@ -32,3 +33,43 @@
void* final_break = sbrk(0);
ASSERT_EQ(final_break, new_break);
}
+
+TEST(unistd, truncate) {
+ TemporaryFile tf;
+ ASSERT_EQ(0, close(tf.fd));
+ ASSERT_EQ(0, truncate(tf.filename, 123));
+
+ struct stat sb;
+ ASSERT_EQ(0, stat(tf.filename, &sb));
+ ASSERT_EQ(123, sb.st_size);
+}
+
+TEST(unistd, truncate64) {
+ TemporaryFile tf;
+ ASSERT_EQ(0, close(tf.fd));
+ ASSERT_EQ(0, truncate64(tf.filename, 123));
+
+ struct stat sb;
+ ASSERT_EQ(0, stat(tf.filename, &sb));
+ ASSERT_EQ(123, sb.st_size);
+}
+
+TEST(unistd, ftruncate) {
+ TemporaryFile tf;
+ ASSERT_EQ(0, ftruncate(tf.fd, 123));
+ ASSERT_EQ(0, close(tf.fd));
+
+ struct stat sb;
+ ASSERT_EQ(0, stat(tf.filename, &sb));
+ ASSERT_EQ(123, sb.st_size);
+}
+
+TEST(unistd, ftruncate64) {
+ TemporaryFile tf;
+ ASSERT_EQ(0, ftruncate64(tf.fd, 123));
+ ASSERT_EQ(0, close(tf.fd));
+
+ struct stat sb;
+ ASSERT_EQ(0, stat(tf.filename, &sb));
+ ASSERT_EQ(123, sb.st_size);
+}