diff options
author | Ulrich Drepper <drepper@redhat.com> | 2004-12-22 20:10:10 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2004-12-22 20:10:10 +0000 |
commit | a334319f6530564d22e775935d9c91663623a1b4 (patch) | |
tree | b5877475619e4c938e98757d518bb1e9cbead751 /sysdeps/unix/sysv/linux/arm | |
parent | 0ecb606cb6cf65de1d9fc8a919bceb4be476c602 (diff) | |
download | glibc-a334319f6530564d22e775935d9c91663623a1b4.tar.gz glibc-a334319f6530564d22e775935d9c91663623a1b4.tar.xz glibc-a334319f6530564d22e775935d9c91663623a1b4.zip |
(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
Diffstat (limited to 'sysdeps/unix/sysv/linux/arm')
68 files changed, 2444 insertions, 0 deletions
diff --git a/sysdeps/unix/sysv/linux/arm/Dist b/sysdeps/unix/sysv/linux/arm/Dist new file mode 100644 index 0000000000..aa9eb1a227 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/Dist @@ -0,0 +1,14 @@ +clone.S +dl-procinfo.h +ioperm.c +setresuid.c +setresgid.c +setfsuid.c +setfsgid.c +sigrestorer.S +bits/armsigctx.h +sys/elf.h +sys/io.h +sys/procfs.h +sys/user.h +oldgetrlimit64.c diff --git a/sysdeps/unix/sysv/linux/arm/Makefile b/sysdeps/unix/sysv/linux/arm/Makefile new file mode 100644 index 0000000000..0ccdbe81f6 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/Makefile @@ -0,0 +1,12 @@ +ifeq ($(subdir),misc) +sysdep_routines += ioperm +sysdep_headers += sys/elf.h sys/io.h +endif + +ifeq ($(subdir),signal) +sysdep_routines += sigrestorer +endif + +ifeq ($(subdir),resource) +sysdep_routines += oldgetrlimit64 +endif diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions new file mode 100644 index 0000000000..2ddb2af2b7 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/Versions @@ -0,0 +1,37 @@ +libc { + GLIBC_2.0 { + # Exception handling support functions from libgcc + __register_frame; __register_frame_table; __deregister_frame; + __frame_state_for; __register_frame_info_table; + } + GLIBC_2.1 { + ioperm; iopl; + inb; inw; inl; + outb; outw; outl; + } + GLIBC_2.2 { + # functions used in other libraries + __xstat64; __fxstat64; __lxstat64; + + # a* + alphasort64; + + # g* + glob64; + + # New rlimit interface + getrlimit; setrlimit; getrlimit64; + + # r* + readdir64; readdir64_r; + + # s* + scandir64; + + # v* + versionsort64; + } + GLIBC_2.3.3 { + posix_fadvise64; posix_fallocate64; + } +} diff --git a/sysdeps/unix/sysv/linux/arm/alphasort64.c b/sysdeps/unix/sysv/linux/arm/alphasort64.c new file mode 100644 index 0000000000..0b5ae47d2f --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/alphasort64.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/alphasort64.c> diff --git a/sysdeps/unix/sysv/linux/arm/bits/armsigctx.h b/sysdeps/unix/sysv/linux/arm/bits/armsigctx.h new file mode 100644 index 0000000000..4530cdbda9 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/bits/armsigctx.h @@ -0,0 +1,73 @@ +/* Definition of `struct sigcontext' for Linux/ARM + Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* The format of struct sigcontext changed between 2.0 and 2.1 kernels. + Fortunately 2.0 puts a magic number in the first word and this is not + a legal value for `trap_no', so we can tell them apart. */ + +/* Early 2.2 and 2.3 kernels do not have the `fault_address' member in + the sigcontext structure. Unfortunately there is no reliable way + to test for its presence and this word will contain garbage for too-old + kernels. Versions 2.2.14 and 2.3.35 (plus later versions) are known to + include this element. */ + +#ifndef __ARMSIGCTX_H +#define __ARMSIGCTX_H 1 + +#include <asm/ptrace.h> + +union k_sigcontext + { + struct + { + unsigned long int trap_no; + unsigned long int error_code; + unsigned long int oldmask; + unsigned long int arm_r0; + unsigned long int arm_r1; + unsigned long int arm_r2; + unsigned long int arm_r3; + unsigned long int arm_r4; + unsigned long int arm_r5; + unsigned long int arm_r6; + unsigned long int arm_r7; + unsigned long int arm_r8; + unsigned long int arm_r9; + unsigned long int arm_r10; + unsigned long int arm_fp; + unsigned long int arm_ip; + unsigned long int arm_sp; + unsigned long int arm_lr; + unsigned long int arm_pc; + unsigned long int arm_cpsr; + unsigned long fault_address; + } v21; + struct + { + unsigned long int magic; + struct pt_regs reg; + unsigned long int trap_no; + unsigned long int error_code; + unsigned long int oldmask; + } v20; +}; + +#define SIGCONTEXT_2_0_MAGIC 0x4B534154 + +#endif /* bits/armsigctx.h */ diff --git a/sysdeps/unix/sysv/linux/arm/bits/fcntl.h b/sysdeps/unix/sysv/linux/arm/bits/fcntl.h new file mode 100644 index 0000000000..3574e750ff --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/bits/fcntl.h @@ -0,0 +1,189 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 1995-1998, 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use <bits/fcntl.h> directly; include <fcntl.h> instead." +#endif + + +#include <sys/types.h> + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECTORY 040000 /* Must be a directory. */ +# define O_NOFOLLOW 0100000 /* Do not follow links. */ +# define O_DIRECT 0200000 /* Direct disk access. */ +# define O_NOATIME 01000000 /* Do not set atime. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0400000 +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ + +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* for old implementation of bsd flock () */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + +__BEGIN_DECLS + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + +__END_DECLS diff --git a/sysdeps/unix/sysv/linux/arm/bits/mman.h b/sysdeps/unix/sysv/linux/arm/bits/mman.h new file mode 100644 index 0000000000..4ec6839685 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/bits/mman.h @@ -0,0 +1,99 @@ +/* Definitions for POSIX memory map interface. Linux/ARM version. + Copyright (C) 1997, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +# error "Never include this file directly. Use <sys/mman.h> instead" +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ +#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of + growsdown vma (mprotect only). */ +#define PROT_GROWSUP 0x02000000 /* Extend change to start of + growsup vma (mprotect only). */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x00100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x00800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x01000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x02000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x04000 /* Don't check for reservations. */ +# define MAP_POPULATE 0x08000 /* Populate (prefault) pagetables. */ +# define MAP_NONBLOCK 0x10000 /* Do not block on IO. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +#endif + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ +#endif diff --git a/sysdeps/unix/sysv/linux/arm/brk.c b/sysdeps/unix/sysv/linux/arm/brk.c new file mode 100644 index 0000000000..153d89358a --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/brk.c @@ -0,0 +1,49 @@ +/* brk system call for Linux/ARM. + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <unistd.h> +#include <sysdep.h> + +/* This must be initialized data because commons can't have aliases. */ +void *__curbrk = 0; + +int +__brk (void *addr) +{ + void *newbrk; + + asm ("mov a1, %1\n" /* save the argment in r0 */ + "swi %2\n" /* do the system call */ + "mov %0, a1;" /* keep the return value */ + : "=r"(newbrk) + : "r"(addr), "i" (SYS_ify (brk)) + : "a1"); + + __curbrk = newbrk; + + if (newbrk < addr) + { + __set_errno (ENOMEM); + return -1; + } + + return 0; +} +weak_alias (__brk, brk) diff --git a/sysdeps/unix/sysv/linux/arm/chown.c b/sysdeps/unix/sysv/linux/arm/chown.c new file mode 100644 index 0000000000..1961622564 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/chown.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/m68k/chown.c> diff --git a/sysdeps/unix/sysv/linux/arm/clone.S b/sysdeps/unix/sysv/linux/arm/clone.S new file mode 100644 index 0000000000..bf07fb3952 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/clone.S @@ -0,0 +1,60 @@ +/* Copyright (C) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Pat Beirne <patb@corelcomputer.com> + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#include <sysdep.h> +#define _ERRNO_H 1 +#include <bits/errno.h> + +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */ + + .text +ENTRY(__clone) + @ sanity check args + cmp r0, #0 + cmpne r1, #0 + moveq r0, #-EINVAL + beq PLTJMP(syscall_error) + + @ insert the args onto the new stack + str r3, [r1, #-4]! + str r0, [r1, #-4]! + + @ do the system call + @ get flags + mov r0, r2 + @ new sp is already in r1 + swi SYS_ify(clone) + movs a1, a1 + blt PLTJMP(C_SYMBOL_NAME(__syscall_error)) + RETINSTR(ne, lr) + + @ pick the function arg and call address off the stack and execute + ldr r0, [sp, #4] + mov lr, pc + ldr pc, [sp] + + @ and we are done, passing the return value through r0 + b PLTJMP(_exit) + +PSEUDO_END (__clone) + +weak_alias (__clone, clone) diff --git a/sysdeps/unix/sysv/linux/arm/dl-procinfo.c b/sysdeps/unix/sysv/linux/arm/dl-procinfo.c new file mode 100644 index 0000000000..9b87a2003d --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/dl-procinfo.c @@ -0,0 +1,64 @@ +/* Data for Linux/ARM version of processor capability information. + Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell <philb@gnu.org>, 2001. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This information must be kept in sync with the _DL_HWCAP_COUNT and + _DL_PLATFORM_COUNT definitions in procinfo.h. + + If anything should be added here check whether the size of each string + is still ok with the given array size. + + All the #ifdefs in the definitions ar equite irritating but + necessary if we want to avoid duplicating the information. There + are three different modes: + + - PROCINFO_DECL is defined. This means we are only interested in + declarations. + + - PROCINFO_DECL is not defined: + + + if SHARED is defined the file is included in an array + initializer. The .element = { ... } syntax is needed. + + + if SHARED is not defined a normal array initialization is + needed. + */ + +#ifndef PROCINFO_CLASS +#define PROCINFO_CLASS +#endif + +#if !defined PROCINFO_DECL && defined SHARED + ._dl_arm_cap_flags +#else +PROCINFO_CLASS const char _dl_arm_cap_flags[8][10] +#endif +#ifndef PROCINFO_DECL += { + "swp", "half", "thumb", "26bit", "fast-mult", "fpa", "vfp", "edsp", + } +#endif +#if !defined SHARED || defined PROCINFO_DECL +; +#else +, +#endif + +#undef PROCINFO_DECL +#undef PROCINFO_CLASS diff --git a/sysdeps/unix/sysv/linux/arm/dl-procinfo.h b/sysdeps/unix/sysv/linux/arm/dl-procinfo.h new file mode 100644 index 0000000000..35b333479b --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/dl-procinfo.h @@ -0,0 +1,86 @@ +/* Linux/ARM version of processor capability information handling macros. + Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell <philb@gnu.org>, 2001. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _DL_PROCINFO_H +#define _DL_PROCINFO_H 1 + +#include <ldsodefs.h> + +#define _DL_HWCAP_COUNT 8 + +/* The kernel provides platform data but it is not interesting. */ +#define _DL_HWCAP_PLATFORM 0 + + +static inline int +__attribute__ ((unused)) +_dl_procinfo (int word) +{ + int i; + + _dl_printf ("AT_HWCAP: "); + + for (i = 0; i < _DL_HWCAP_COUNT; ++i) + if (word & (1 << i)) + _dl_printf (" %s", GLRO(dl_arm_cap_flags)[i]); + + _dl_printf ("\n"); + + return 0; +} + +static inline const char * +__attribute__ ((unused)) +_dl_hwcap_string (int idx) +{ + return GLRO(dl_arm_cap_flags)[idx]; +}; + +enum +{ + HWCAP_ARM_SWP = 1 << 0, + HWCAP_ARM_HALF = 1 << 1, + HWCAP_ARM_THUMB = 1 << 2, + HWCAP_ARM_26BIT = 1 << 3, + HWCAP_ARM_FAST_MULT = 1 << 4, + HWCAP_ARM_FPA = 1 << 5, + HWCAP_ARM_VFP = 1 << 6, + HWCAP_ARM_EDSP = 1 << 7, + + HWCAP_IMPORTANT = (HWCAP_ARM_HALF | HWCAP_ARM_FAST_MULT) +}; + +static inline int +__attribute__ ((unused)) +_dl_string_hwcap (const char *str) +{ + int i; + + for (i = 0; i < _DL_HWCAP_COUNT; i++) + { + if (strcmp (str, GLRO(dl_arm_cap_flags)[i]) == 0) + return i; + } + return -1; +}; + +#define _dl_string_platform(str) (-1) + +#endif /* dl-procinfo.h */ diff --git a/sysdeps/unix/sysv/linux/arm/fchown.c b/sysdeps/unix/sysv/linux/arm/fchown.c new file mode 100644 index 0000000000..3a69ecc9e7 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/fchown.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/fchown.c> diff --git a/sysdeps/unix/sysv/linux/arm/fcntl.c b/sysdeps/unix/sysv/linux/arm/fcntl.c new file mode 100644 index 0000000000..ea951bc4f9 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/fcntl.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/fcntl.c> diff --git a/sysdeps/unix/sysv/linux/arm/fxstat.c b/sysdeps/unix/sysv/linux/arm/fxstat.c new file mode 100644 index 0000000000..4f219f0b9d --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/fxstat.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/fxstat.c> diff --git a/sysdeps/unix/sysv/linux/arm/getdents64.c b/sysdeps/unix/sysv/linux/arm/getdents64.c new file mode 100644 index 0000000000..0c75fb5a06 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/getdents64.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/getdents64.c> diff --git a/sysdeps/unix/sysv/linux/arm/getegid.c b/sysdeps/unix/sysv/linux/arm/getegid.c new file mode 100644 index 0000000000..37b4b4a530 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/getegid.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/getegid.c> diff --git a/sysdeps/unix/sysv/linux/arm/geteuid.c b/sysdeps/unix/sysv/linux/arm/geteuid.c new file mode 100644 index 0000000000..ebcb555b5e --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/geteuid.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/geteuid.c> diff --git a/sysdeps/unix/sysv/linux/arm/getgid.c b/sysdeps/unix/sysv/linux/arm/getgid.c new file mode 100644 index 0000000000..0a4d6061f0 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/getgid.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/getgid.c> diff --git a/sysdeps/unix/sysv/linux/arm/getgroups.c b/sysdeps/unix/sysv/linux/arm/getgroups.c new file mode 100644 index 0000000000..102ea24e14 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/getgroups.c @@ -0,0 +1,2 @@ +/* We also have to rewrite the kernel gid_t to the user land type. */ +#include <sysdeps/unix/sysv/linux/i386/getgroups.c> diff --git a/sysdeps/unix/sysv/linux/arm/getresgid.c b/sysdeps/unix/sysv/linux/arm/getresgid.c new file mode 100644 index 0000000000..b703a414cc --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/getresgid.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/getresgid.c> diff --git a/sysdeps/unix/sysv/linux/arm/getresuid.c b/sysdeps/unix/sysv/linux/arm/getresuid.c new file mode 100644 index 0000000000..0b14cefe34 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/getresuid.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/getresuid.c> diff --git a/sysdeps/unix/sysv/linux/arm/getrlimit.c b/sysdeps/unix/sysv/linux/arm/getrlimit.c new file mode 100644 index 0000000000..fc06dbd641 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/getrlimit.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/getrlimit.c> diff --git a/sysdeps/unix/sysv/linux/arm/getrlimit64.c b/sysdeps/unix/sysv/linux/arm/getrlimit64.c new file mode 100644 index 0000000000..fef018f471 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/getrlimit64.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/getrlimit64.c> diff --git a/sysdeps/unix/sysv/linux/arm/getuid.c b/sysdeps/unix/sysv/linux/arm/getuid.c new file mode 100644 index 0000000000..d682c79a49 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/getuid.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/getuid.c> diff --git a/sysdeps/unix/sysv/linux/arm/glob64.c b/sysdeps/unix/sysv/linux/arm/glob64.c new file mode 100644 index 0000000000..82a9a296a7 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/glob64.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/glob64.c> diff --git a/sysdeps/unix/sysv/linux/arm/ioperm.c b/sysdeps/unix/sysv/linux/arm/ioperm.c new file mode 100644 index 0000000000..558b485b61 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/ioperm.c @@ -0,0 +1,274 @@ +/* Copyright (C) 1998, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Phil Blundell, based on the Alpha version by + David Mosberger. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* I/O port access on the ARM is something of a fiction. What we do is to + map an appropriate area of /dev/mem into user space so that a program + can blast away at the hardware in such a way as to generate I/O cycles + on the bus. To insulate user code from dependencies on particular + hardware we don't allow calls to inb() and friends to be inlined, but + force them to come through code in here every time. Performance-critical + registers tend to be memory mapped these days so this should be no big + problem. */ + +/* Once upon a time this file used mprotect to enable and disable + access to particular areas of I/O space. Unfortunately the + mprotect syscall also has the side effect of enabling caching for + the area affected (this is a kernel limitation). So we now just + enable all the ports all of the time. */ + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <sys/types.h> +#include <sys/mman.h> + +#include <asm/page.h> +#include <sys/sysctl.h> + +#define PATH_ARM_SYSTYPE "/etc/arm_systype" +#define PATH_CPUINFO "/proc/cpuinfo" + +#define MAX_PORT 0x10000 + +static struct { + unsigned long int base; + unsigned long int io_base; + unsigned int shift; + unsigned int initdone; /* since all the above could be 0 */ +} io; + +#define IO_BASE_FOOTBRIDGE 0x7c000000 +#define IO_SHIFT_FOOTBRIDGE 0 + +static struct platform { + const char *name; + unsigned long int io_base; + unsigned int shift; +} platform[] = { + /* All currently supported platforms are in fact the same. :-) */ + {"Chalice-CATS", IO_BASE_FOOTBRIDGE, IO_SHIFT_FOOTBRIDGE}, + {"DEC-EBSA285", IO_BASE_FOOTBRIDGE, IO_SHIFT_FOOTBRIDGE}, + {"Corel-NetWinder", IO_BASE_FOOTBRIDGE, IO_SHIFT_FOOTBRIDGE}, + {"Rebel-NetWinder", IO_BASE_FOOTBRIDGE, IO_SHIFT_FOOTBRIDGE}, +}; + +#define IO_ADDR(port) (io.base + ((port) << io.shift)) + +/* + * Initialize I/O system. There are several ways to get the information + * we need. Each is tried in turn until one succeeds. + * + * 1. Sysctl (CTL_BUS, BUS_ISA, ISA_*). This is the preferred method + * but not all kernels support it. + * + * 2. Read the value (not the contents) of symlink PATH_ARM_SYSTYPE. + * - If it matches one of the entries in the table above, use the + * corresponding values. + * - If it begins with a number, assume this is a previously + * unsupported system and the values encode, in order, + * "<io_base>,<port_shift>". + * + * 3. Lookup the "system type" field in /proc/cpuinfo. Again, if it + * matches an entry in the platform[] table, use the corresponding + * values. + */ + +static int +init_iosys (void) +{ + char systype[256]; + int i, n; + static int iobase_name[] = { CTL_BUS, BUS_ISA, BUS_ISA_PORT_BASE }; + static int ioshift_name[] = { CTL_BUS, BUS_ISA, BUS_ISA_PORT_SHIFT }; + size_t len = sizeof(io.base); + + if (! sysctl (iobase_name, 3, &io.io_base, &len, NULL, 0) + && ! sysctl (ioshift_name, 3, &io.shift, &len, NULL, 0)) + { + io.initdone = 1; + return 0; + } + + n = readlink (PATH_ARM_SYSTYPE, systype, sizeof (systype) - 1); + if (n > 0) + { + systype[n] = '\0'; + if (isdigit (systype[0])) + { + if (sscanf (systype, "%li,%i", &io.io_base, &io.shift) == 2) + { + io.initdone = 1; + return 0; + } + /* else we're likely going to fail with the system match below */ + } + } + else + { + FILE * fp; + + fp = fopen (PATH_CPUINFO, "r"); + if (! fp) + return -1; + while ((n = fscanf (fp, "Hardware\t: %256[^\n]\n", systype)) + != EOF) + { + if (n == 1) + break; + else + fgets (systype, 256, fp); + } + fclose (fp); + + if (n == EOF) + { + /* this can happen if the format of /proc/cpuinfo changes... */ + fprintf (stderr, + "ioperm: Unable to determine system type.\n" + "\t(May need " PATH_ARM_SYSTYPE " symlink?)\n"); + __set_errno (ENODEV); + return -1; + } + } + + /* translate systype name into i/o system: */ + for (i = 0; i < sizeof (platform) / sizeof (platform[0]); ++i) + { + if (strcmp (platform[i].name, systype) == 0) + { + io.shift = platform[i].shift; + io.io_base = platform[i].io_base; + io.initdone = 1; + return 0; + } + } + + /* systype is not a known platform name... */ + __set_errno (ENODEV); + return -1; +} + +int +_ioperm (unsigned long int from, unsigned long int num, int turn_on) +{ + if (! io.initdone && init_iosys () < 0) + return -1; + + /* this test isn't as silly as it may look like; consider overflows! */ + if (from >= MAX_PORT || from + num > MAX_PORT) + { + __set_errno (EINVAL); + return -1; + } + + if (turn_on) + { + if (! io.base) + { + int fd; + + fd = open ("/dev/mem", O_RDWR); + if (fd < 0) + return -1; + + io.base = + (unsigned long int) __mmap (0, MAX_PORT << io.shift, + PROT_READ | PROT_WRITE, + MAP_SHARED, fd, io.io_base); + close (fd); + if ((long) io.base == -1) + return -1; + } + } + + return 0; +} + + +int +_iopl (unsigned int level) +{ + if (level > 3) + { + __set_errno (EINVAL); + return -1; + } + if (level) + { + return _ioperm (0, MAX_PORT, 1); + } + return 0; +} + + +void +_outb (unsigned char b, unsigned long int port) +{ + *((volatile unsigned char *)(IO_ADDR (port))) = b; +} + + +void +_outw (unsigned short b, unsigned long int port) +{ + *((volatile unsigned short *)(IO_ADDR (port))) = b; +} + + +void +_outl (unsigned int b, unsigned long int port) +{ + *((volatile unsigned long *)(IO_ADDR (port))) = b; +} + + +unsigned int +_inb (unsigned long int port) +{ + return *((volatile unsigned char *)(IO_ADDR (port))); +} + + +unsigned int +_inw (unsigned long int port) +{ + return *((volatile unsigned short *)(IO_ADDR (port))); +} + + +unsigned int +_inl (unsigned long int port) +{ + return *((volatile unsigned long *)(IO_ADDR (port))); +} + +weak_alias (_ioperm, ioperm); +weak_alias (_iopl, iopl); +weak_alias (_inb, inb); +weak_alias (_inw, inw); +weak_alias (_inl, inl); +weak_alias (_outb, outb); +weak_alias (_outw, outw); +weak_alias (_outl, outl); diff --git a/sysdeps/unix/sysv/linux/arm/lchown.c b/sysdeps/unix/sysv/linux/arm/lchown.c new file mode 100644 index 0000000000..c89de99ba2 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/lchown.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/lchown.c> diff --git a/sysdeps/unix/sysv/linux/arm/lockf64.c b/sysdeps/unix/sysv/linux/arm/lockf64.c new file mode 100644 index 0000000000..a88f5a784a --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/lockf64.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/lockf64.c> diff --git a/sysdeps/unix/sysv/linux/arm/lxstat.c b/sysdeps/unix/sysv/linux/arm/lxstat.c new file mode 100644 index 0000000000..2371cd9719 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/lxstat.c @@ -0,0 +1,2 @@ +#include <sysdeps/unix/sysv/linux/i386/lxstat.c> + diff --git a/sysdeps/unix/sysv/linux/arm/mmap.S b/sysdeps/unix/sysv/linux/arm/mmap.S new file mode 100644 index 0000000000..cf6f253378 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/mmap.S @@ -0,0 +1,92 @@ +/* Copyright (C) 1998, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <kernel-features.h> + +#define EINVAL 22 + + .text + +ENTRY (__mmap) +# ifdef __ASSUME_MMAP2_SYSCALL + /* This code is actually a couple of cycles slower than the + sys_mmap version below, so it might seem like a loss. But the + code path inside the kernel is sufficiently much shorter to + make it a net gain to use mmap2 when it's known to be + available. */ + + /* shuffle args */ + str r5, [sp, #-4]! + ldr r5, [sp, #8] + str r4, [sp, #-4]! + ldr r4, [sp, #8] + + /* convert offset to pages */ + movs ip, r5, lsl #20 + bne .Linval + mov r5, r5, lsr #12 + + /* do the syscall */ + swi SYS_ify (mmap2) + + /* restore registers */ +2: + ldr r4, [sp], #4 + ldr r5, [sp], #4 + + cmn r0, $4096 + RETINSTR(cc, lr) + b PLTJMP(syscall_error) + +.Linval: + mov r0, #-EINVAL + b 2b +# else + /* Because we can only get five args through the syscall interface, and + mmap() takes six, we need to build a parameter block and pass its + address instead. The 386 port does a similar trick. */ + + /* This code previously moved sp into ip and stored the args using + stmdb ip!, {a1-a4}. It did not modify sp, so the stack never had + to be restored after the syscall completed. It saved an + instruction and meant no stack cleanup work was required. + + This will not work in the case of a mmap call being interrupted + by a signal. If the signal handler uses any stack the arguments + to mmap will be trashed. The results of a restart of mmap are + then unpredictable. */ + + /* store args on the stack */ + stmdb sp!, {a1-a4} + + /* do the syscall */ + mov a1, sp + swi SYS_ify (mmap) + + /* pop args off the stack. */ + add sp, sp, #16 + + cmn r0, $4096 + RETINSTR(cc, lr) + b PLTJMP(syscall_error); +#endif + +PSEUDO_END (__mmap) + +weak_alias (__mmap, mmap) diff --git a/sysdeps/unix/sysv/linux/arm/mmap64.S b/sysdeps/unix/sysv/linux/arm/mmap64.S new file mode 100644 index 0000000000..b4b712c2f2 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/mmap64.S @@ -0,0 +1,80 @@ +/* Copyright (C) 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> + +#define EINVAL 22 +#define ENOSYS 38 + +#include "kernel-features.h" + + /* The mmap2 system call takes six arguments, all in registers. */ + .text +ENTRY (__mmap64) +#ifdef __NR_mmap2 + ldr ip, [sp, $4] @ offset low part + str r5, [sp, #-4]! + ldr r5, [sp, $12] @ offset high part + str r4, [sp, #-4]! + movs r4, ip, lsl $20 @ check that offset is page-aligned + mov ip, ip, lsr $12 + moveqs r4, r5, lsr $12 @ check for overflow + bne .Linval + ldr r4, [sp, $8] @ load fd + orr r5, ip, r5, lsl $20 @ compose page offset + mov ip, r0 + swi SYS_ify (mmap2) + cmn r0, $4096 +# ifdef __ASSUME_MMAP2_SYSCALL + ldr r4, [sp], #4 + ldr r5, [sp], #4 + RETINSTR(cc, lr) + b PLTJMP(syscall_error) +# else + ldrcc r4, [sp], #4 + ldrcc r5, [sp], #4 + RETINSTR(cc, lr) + cmn r0, $ENOSYS + bne .Lerror + /* The current kernel does not support mmap2. Fall back to plain + mmap if the offset is small enough. */ + ldr r5, [sp, $16] + mov r0, ip @ first arg was clobbered + teq r5, $0 + ldreq r4, [sp], #4 + ldreq r5, [sp], #4 + beq PLTJMP(__mmap) +# endif +.Linval: + mov r0, $-EINVAL +.Lerror: + ldr r4, [sp], #4 + ldr r5, [sp], #4 + b PLTJMP(syscall_error) +#else + /* The kernel headers do not support mmap2. Fall back to plain + mmap if the offset is small enough. */ + ldr ip, [sp, $8] + teq ip, $0 + beq PLTJMP(__mmap) + mov r0, $-EINVAL + b PLTJMP(syscall_error) +#endif +PSEUDO_END (__mmap64) + +weak_alias (__mmap64, mmap64) diff --git a/sysdeps/unix/sysv/linux/arm/msgctl.c b/sysdeps/unix/sysv/linux/arm/msgctl.c new file mode 100644 index 0000000000..9f9b8431a3 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/msgctl.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/msgctl.c> diff --git a/sysdeps/unix/sysv/linux/arm/oldgetrlimit64.c b/sysdeps/unix/sysv/linux/arm/oldgetrlimit64.c new file mode 100644 index 0000000000..4c27e957bf --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/oldgetrlimit64.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/oldgetrlimit64.c> diff --git a/sysdeps/unix/sysv/linux/arm/profil-counter.h b/sysdeps/unix/sysv/linux/arm/profil-counter.h new file mode 100644 index 0000000000..7639883f10 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/profil-counter.h @@ -0,0 +1,37 @@ +/* Low-level statistical profiling support function. Linux/ARM version. + Copyright (C) 1996, 1997, 1998, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <signal.h> +#include <bits/armsigctx.h> + +void +profil_counter (int signo, int _a2, int _a3, int _a4, union k_sigcontext sc) +{ + void *pc; + if (sc.v20.magic == SIGCONTEXT_2_0_MAGIC) + pc = (void *) sc.v20.reg.ARM_pc; + else + pc = (void *) sc.v21.arm_pc; + profil_count (pc); + + /* This is a hack to prevent the compiler from implementing the + above function call as a sibcall. The sibcall would overwrite + the signal context. */ + asm volatile (""); +} diff --git a/sysdeps/unix/sysv/linux/arm/readdir64.c b/sysdeps/unix/sysv/linux/arm/readdir64.c new file mode 100644 index 0000000000..2ea26dd409 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/readdir64.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/readdir64.c> diff --git a/sysdeps/unix/sysv/linux/arm/readdir64_r.c b/sysdeps/unix/sysv/linux/arm/readdir64_r.c new file mode 100644 index 0000000000..9f54f897e3 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/readdir64_r.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/readdir64_r.c> diff --git a/sysdeps/unix/sysv/linux/arm/register-dump.h b/sysdeps/unix/sysv/linux/arm/register-dump.h new file mode 100644 index 0000000000..2baccb2cb7 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/register-dump.h @@ -0,0 +1,166 @@ +/* Dump registers. + Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell <pb@nexus.co.uk>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sys/uio.h> +#include <stdio-common/_itoa.h> +#include <bits/armsigctx.h> + +/* We will print the register dump in this format: + + R0: XXXXXXXX R1: XXXXXXXX R2: XXXXXXXX R3: XXXXXXXX + R4: XXXXXXXX R5: XXXXXXXX R6: XXXXXXXX R7: XXXXXXXX + R8: XXXXXXXX R9: XXXXXXXX SL: XXXXXXXX FP: XXXXXXXX + IP: XXXXXXXX SP: XXXXXXXX LR: XXXXXXXX PC: XXXXXXXX + + CPSR: XXXXXXXX + + Trap: XXXXXXXX Error: XXXXXXXX OldMask: XXXXXXXX + Addr: XXXXXXXX + + */ + +static void +hexvalue (unsigned long int value, char *buf, size_t len) +{ + char *cp = _itoa_word (value, buf + len, 16, 0); + while (cp > buf) + *--cp = '0'; +} + +static void +register_dump (int fd, union k_sigcontext *ctx) +{ + char regs[21][8]; + struct iovec iov[97]; + size_t nr = 0; + +#define ADD_STRING(str) \ + iov[nr].iov_base = (char *) str; \ + iov[nr].iov_len = strlen (str); \ + ++nr +#define ADD_MEM(str, len) \ + iov[nr].iov_base = str; \ + iov[nr].iov_len = len; \ + ++nr + + /* Generate strings of register contents. */ + if (ctx->v20.magic == SIGCONTEXT_2_0_MAGIC) + { + hexvalue (ctx->v20.reg.ARM_r0, regs[0], 8); + hexvalue (ctx->v20.reg.ARM_r1, regs[1], 8); + hexvalue (ctx->v20.reg.ARM_r2, regs[2], 8); + hexvalue (ctx->v20.reg.ARM_r3, regs[3], 8); + hexvalue (ctx->v20.reg.ARM_r4, regs[4], 8); + hexvalue (ctx->v20.reg.ARM_r5, regs[5], 8); + hexvalue (ctx->v20.reg.ARM_r6, regs[6], 8); + hexvalue (ctx->v20.reg.ARM_r7, regs[7], 8); + hexvalue (ctx->v20.reg.ARM_r8, regs[8], 8); + hexvalue (ctx->v20.reg.ARM_r9, regs[9], 8); + hexvalue (ctx->v20.reg.ARM_r10, regs[10], 8); + hexvalue (ctx->v20.reg.ARM_fp, regs[11], 8); + hexvalue (ctx->v20.reg.ARM_ip, regs[12], 8); + hexvalue (ctx->v20.reg.ARM_sp, regs[13], 8); + hexvalue (ctx->v20.reg.ARM_lr, regs[14], 8); + hexvalue (ctx->v20.reg.ARM_pc, regs[15], 8); + hexvalue (ctx->v20.reg.ARM_cpsr, regs[16], 8); + hexvalue (ctx->v20.trap_no, regs[17], 8); + hexvalue (ctx->v20.error_code, regs[18], 8); + hexvalue (ctx->v20.oldmask, regs[19], 8); + } + else + { + hexvalue (ctx->v21.arm_r0, regs[0], 8); + hexvalue (ctx->v21.arm_r1, regs[1], 8); + hexvalue (ctx->v21.arm_r2, regs[2], 8); + hexvalue (ctx->v21.arm_r3, regs[3], 8); + hexvalue (ctx->v21.arm_r4, regs[4], 8); + hexvalue (ctx->v21.arm_r5, regs[5], 8); + hexvalue (ctx->v21.arm_r6, regs[6], 8); + hexvalue (ctx->v21.arm_r7, regs[7], 8); + hexvalue (ctx->v21.arm_r8, regs[8], 8); + hexvalue (ctx->v21.arm_r9, regs[9], 8); + hexvalue (ctx->v21.arm_r10, regs[10], 8); + hexvalue (ctx->v21.arm_fp, regs[11], 8); + hexvalue (ctx->v21.arm_ip, regs[12], 8); + hexvalue (ctx->v21.arm_sp, regs[13], 8); + hexvalue (ctx->v21.arm_lr, regs[14], 8); + hexvalue (ctx->v21.arm_pc, regs[15], 8); + hexvalue (ctx->v21.arm_cpsr, regs[16], 8); + hexvalue (ctx->v21.trap_no, regs[17], 8); + hexvalue (ctx->v21.error_code, regs[18], 8); + hexvalue (ctx->v21.oldmask, regs[19], 8); + hexvalue (ctx->v21.fault_address, regs[20], 8); + } + + /* Generate the output. */ + ADD_STRING ("Register dump:\n\n R0: "); + ADD_MEM (regs[0], 8); + ADD_STRING (" R1: "); + ADD_MEM (regs[1], 8); + ADD_STRING (" R2: "); + ADD_MEM (regs[2], 8); + ADD_STRING (" R3: "); + ADD_MEM (regs[3], 8); + ADD_STRING ("\n R4: "); + ADD_MEM (regs[4], 8); + ADD_STRING (" R5: "); + ADD_MEM (regs[5], 8); + ADD_STRING (" R6: "); + ADD_MEM (regs[6], 8); + ADD_STRING (" R7: "); + ADD_MEM (regs[7], 8); + ADD_STRING ("\n R8: "); + ADD_MEM (regs[8], 8); + ADD_STRING (" R9: "); + ADD_MEM (regs[9], 8); + ADD_STRING (" SL: "); + ADD_MEM (regs[10], 8); + ADD_STRING (" FP: "); + ADD_MEM (regs[11], 8); + ADD_STRING ("\n IP: "); + ADD_MEM (regs[12], 8); + ADD_STRING (" SP: "); + ADD_MEM (regs[13], 8); + ADD_STRING (" LR: "); + ADD_MEM (regs[14], 8); + ADD_STRING (" PC: "); + ADD_MEM (regs[15], 8); + ADD_STRING ("\n\n CPSR: "); + ADD_MEM (regs[16], 8); + ADD_STRING ("\n\n Trap: "); + ADD_MEM (regs[17], 8); + ADD_STRING (" Error: "); + ADD_MEM (regs[18], 8); + ADD_STRING (" OldMask: "); + ADD_MEM (regs[19], 8); + if (ctx->v20.magic != SIGCONTEXT_2_0_MAGIC) + { + ADD_STRING ("\n Addr: "); + ADD_MEM (regs[20], 8); + } + + ADD_STRING ("\n"); + + /* Write the stuff out. */ + writev (fd, iov, nr); +} + + +#define REGISTER_DUMP register_dump (fd, &ctx) diff --git a/sysdeps/unix/sysv/linux/arm/scandir64.c b/sysdeps/unix/sysv/linux/arm/scandir64.c new file mode 100644 index 0000000000..506fd8877c --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/scandir64.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/scandir64.c> diff --git a/sysdeps/unix/sysv/linux/arm/semctl.c b/sysdeps/unix/sysv/linux/arm/semctl.c new file mode 100644 index 0000000000..e9b1a483c9 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/semctl.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/semctl.c> diff --git a/sysdeps/unix/sysv/linux/arm/setegid.c b/sysdeps/unix/sysv/linux/arm/setegid.c new file mode 100644 index 0000000000..2e3a54c893 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/setegid.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/setegid.c> diff --git a/sysdeps/unix/sysv/linux/arm/seteuid.c b/sysdeps/unix/sysv/linux/arm/seteuid.c new file mode 100644 index 0000000000..18e41d08c1 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/seteuid.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/seteuid.c> diff --git a/sysdeps/unix/sysv/linux/arm/setfsgid.c b/sysdeps/unix/sysv/linux/arm/setfsgid.c new file mode 100644 index 0000000000..0886712569 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/setfsgid.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/setfsgid.c> diff --git a/sysdeps/unix/sysv/linux/arm/setfsuid.c b/sysdeps/unix/sysv/linux/arm/setfsuid.c new file mode 100644 index 0000000000..a9f22eb8ab --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/setfsuid.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/setfsuid.c> diff --git a/sysdeps/unix/sysv/linux/arm/setgid.c b/sysdeps/unix/sysv/linux/arm/setgid.c new file mode 100644 index 0000000000..377021d9ec --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/setgid.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/setgid.c> diff --git a/sysdeps/unix/sysv/linux/arm/setgroups.c b/sysdeps/unix/sysv/linux/arm/setgroups.c new file mode 100644 index 0000000000..0e7086278f --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/setgroups.c @@ -0,0 +1,2 @@ +/* We also have to rewrite the kernel gid_t to the user land type. */ +#include <sysdeps/unix/sysv/linux/i386/setgroups.c> diff --git a/sysdeps/unix/sysv/linux/arm/setregid.c b/sysdeps/unix/sysv/linux/arm/setregid.c new file mode 100644 index 0000000000..99c57ad20f --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/setregid.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/setregid.c> diff --git a/sysdeps/unix/sysv/linux/arm/setresgid.c b/sysdeps/unix/sysv/linux/arm/setresgid.c new file mode 100644 index 0000000000..daca1a4833 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/setresgid.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/setresgid.c> diff --git a/sysdeps/unix/sysv/linux/arm/setresuid.c b/sysdeps/unix/sysv/linux/arm/setresuid.c new file mode 100644 index 0000000000..3aeabe9ad7 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/setresuid.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/setresuid.c> diff --git a/sysdeps/unix/sysv/linux/arm/setreuid.c b/sysdeps/unix/sysv/linux/arm/setreuid.c new file mode 100644 index 0000000000..8ad61226e9 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/setreuid.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/setreuid.c> diff --git a/sysdeps/unix/sysv/linux/arm/setrlimit.c b/sysdeps/unix/sysv/linux/arm/setrlimit.c new file mode 100644 index 0000000000..bfaef74c38 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/setrlimit.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/setrlimit.c> diff --git a/sysdeps/unix/sysv/linux/arm/setuid.c b/sysdeps/unix/sysv/linux/arm/setuid.c new file mode 100644 index 0000000000..de394379be --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/setuid.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/setuid.c> diff --git a/sysdeps/unix/sysv/linux/arm/shmctl.c b/sysdeps/unix/sysv/linux/arm/shmctl.c new file mode 100644 index 0000000000..7eac6380dd --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/shmctl.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/shmctl.c> diff --git a/sysdeps/unix/sysv/linux/arm/sigaction.c b/sysdeps/unix/sysv/linux/arm/sigaction.c new file mode 100644 index 0000000000..81b29adb2b --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/sigaction.c @@ -0,0 +1,165 @@ +/* Copyright (C) 1997,1998,1999,2000,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <signal.h> +#include <string.h> + +#include <sysdep.h> +#include <sys/syscall.h> +#include <kernel-features.h> + +/* The difference here is that the sigaction structure used in the + kernel is not the same as we use in the libc. Therefore we must + translate it here. */ +#include <kernel_sigaction.h> + +/* The variable is shared between all wrappers around signal handling + functions which have RT equivalents. */ +int __libc_missing_rt_sigs; + +#define SA_RESTORER 0x04000000 + +extern void __default_sa_restorer(void); +extern void __default_rt_sa_restorer(void); + +/* When RT signals are in use we need to use a different return stub. */ +#ifdef __NR_rt_sigreturn +#define choose_restorer(flags) \ + (flags & SA_SIGINFO) ? __default_rt_sa_restorer \ + : __default_sa_restorer +#else +#define choose_restorer(flags) \ + __default_sa_restorer +#endif + +/* If ACT is not NULL, change the action for SIG to *ACT. + If OACT is not NULL, put the old action for SIG in *OACT. */ +int +__libc_sigaction (sig, act, oact) + int sig; + const struct sigaction *act; + struct sigaction *oact; +{ +#ifndef __ASSUME_REALTIME_SIGNALS + struct old_kernel_sigaction k_sigact, k_osigact; +#endif + int result; + +#ifdef __NR_rt_sigaction + /* First try the RT signals. */ +# ifndef __ASSUME_REALTIME_SIGNALS + if (!__libc_missing_rt_sigs) +# endif + { + struct kernel_sigaction kact, koact; +# ifndef __ASSUME_REALTIME_SIGNALS + int saved_errno = errno; +# endif + + if (act) + { + kact.k_sa_handler = act->sa_handler; + memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t)); + kact.sa_flags = act->sa_flags; +# ifdef HAVE_SA_RESTORER + /* If the user specified SA_ONSTACK this means she is trying to + use the old-style stack switching. Unfortunately this + requires the sa_restorer field so we cannot install our own + handler. (In fact the user is likely to be out of luck anyway + since the kernel currently only supports stack switching via + the X/Open sigaltstack interface, but we allow for the + possibility that this might change in the future.) */ + if (kact.sa_flags & (SA_RESTORER | SA_ONSTACK)) + kact.sa_restorer = act->sa_restorer; + else + { + kact.sa_restorer = choose_restorer (kact.sa_flags); + kact.sa_flags |= SA_RESTORER; + } +# endif + } + + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ + result = INLINE_SYSCALL (rt_sigaction, 4, sig, + act ? __ptrvalue (&kact) : NULL, + oact ? __ptrvalue (&koact) : NULL, _NSIG / 8); + +# ifndef __ASSUME_REALTIME_SIGNALS + if (result >= 0 || errno != ENOSYS) +# endif + { + if (oact && result >= 0) + { + oact->sa_handler = koact.k_sa_handler; + memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t)); + oact->sa_flags = koact.sa_flags; +# ifdef HAVE_SA_RESTORER + oact->sa_restorer = koact.sa_restorer; +# endif + } + return result; + } + +# ifndef __ASSUME_REALTIME_SIGNALS + __set_errno (saved_errno); + __libc_missing_rt_sigs = 1; +# endif + } +#endif + +#ifndef __ASSUME_REALTIME_SIGNALS + if (act) + { + k_sigact.k_sa_handler = act->sa_handler; + k_sigact.sa_mask = act->sa_mask.__val[0]; + k_sigact.sa_flags = act->sa_flags; +# ifdef HAVE_SA_RESTORER + /* See the comments above for why we test SA_ONSTACK. */ + if (k_sigact.sa_flags & (SA_RESTORER | SA_ONSTACK)) + k_sigact.sa_restorer = act->sa_restorer; + else + { + k_sigact.sa_restorer = choose_restorer (k_sigact.sa_flags); + k_sigact.sa_flags |= SA_RESTORER; + } +# endif + } + result = INLINE_SYSCALL (sigaction, 3, sig, + act ? __ptrvalue (&k_sigact) : NULL, + oact ? __ptrvalue (&k_osigact) : NULL); + if (oact && result >= 0) + { + oact->sa_handler = k_osigact.k_sa_handler; + oact->sa_mask.__val[0] = k_osigact.sa_mask; + oact->sa_flags = k_osigact.sa_flags; +# ifdef HAVE_SA_RESTORER + oact->sa_restorer = k_osigact.sa_restorer; +# endif + } + return result; +#endif +} +libc_hidden_def (__libc_sigaction) + +#ifndef LIBC_SIGACTION +weak_alias (__libc_sigaction, __sigaction) +libc_hidden_weak (__sigaction) +weak_alias (__libc_sigaction, sigaction) +#endif diff --git a/sysdeps/unix/sysv/linux/arm/sigcontextinfo.h b/sysdeps/unix/sysv/linux/arm/sigcontextinfo.h new file mode 100644 index 0000000000..30c2e3a6ce --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/sigcontextinfo.h @@ -0,0 +1,51 @@ +/* Copyright (C) 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell <philb@gnu.org>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <bits/armsigctx.h> +#include "kernel-features.h" + +#define SIGCONTEXT int _a2, int _a3, int _a4, union k_sigcontext +#define SIGCONTEXT_EXTRA_ARGS _a2, _a3, _a4, + +/* The sigcontext structure changed between 2.0 and 2.1 kernels. On any + modern system we should be able to assume that the "new" format will be + in use. */ +#if __LINUX_KERNEL_VERSION > 131328 + +#define GET_PC(ctx) ((void *) ctx.v21.arm_pc) +#define GET_FRAME(ctx) ADVANCE_STACK_FRAME ((void *) ctx.v21.arm_fp) +#define GET_STACK(ctx) ((void *) ctx.v21.arm_sp) + +#else + +#define GET_PC(ctx) ((void *)((ctx.v20.magic == SIGCONTEXT_2_0_MAGIC) ? \ + ctx.v20.reg.ARM_pc : ctx.v21.arm_pc)) +#define GET_FRAME(ctx) \ + ADVANCE_STACK_FRAME((void *)((ctx.v20.magic == SIGCONTEXT_2_0_MAGIC) ? \ + ctx.v20.reg.ARM_fp : ctx.v21.arm_fp)) +#define GET_STACK(ctx) ((void *)((ctx.v20.magic == SIGCONTEXT_2_0_MAGIC) ? \ + ctx.v20.reg.ARM_sp : ctx.v21.arm_sp)) + +#endif + +#define ADVANCE_STACK_FRAME(frm) \ + ((struct layout *)frm - 1) + +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/sysdeps/unix/sysv/linux/arm/sigrestorer.S b/sysdeps/unix/sysv/linux/arm/sigrestorer.S new file mode 100644 index 0000000000..98e33cb8bc --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/sigrestorer.S @@ -0,0 +1,33 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> + +/* If no SA_RESTORER function was specified by the application we use + one of these. This avoids the need for the kernel to synthesise a return + instruction on the stack, which would involve expensive cache flushes. */ + +ENTRY(__default_sa_restorer) + swi SYS_ify(sigreturn) + +#ifdef __NR_rt_sigreturn + +ENTRY(__default_rt_sa_restorer) + swi SYS_ify(rt_sigreturn) + +#endif diff --git a/sysdeps/unix/sysv/linux/arm/socket.S b/sysdeps/unix/sysv/linux/arm/socket.S new file mode 100644 index 0000000000..212a489afe --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/socket.S @@ -0,0 +1,123 @@ +/* Copyright (C) 1995, 1996, 1997, 1998, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep-cancel.h> +#include <socketcall.h> + +#define P(a, b) P2(a, b) +#define P2(a, b) a##b + + .text +/* The socket-oriented system calls are handled unusally in Linux. + They are all gated through the single `socketcall' system call number. + `socketcall' takes two arguments: the first is the subcode, specifying + which socket function is being called; and the second is a pointer to + the arguments to the specific function. + + The .S files for the other calls just #define socket and #include this. */ + +#ifndef __socket +#define __socket P(__,socket) +#endif + +#define PUSHARGS_1 str a1, [sp, $-4]! +#define PUSHARGS_2 stmfd sp!, {a1, a2} +#define PUSHARGS_3 stmfd sp!, {a1, a2, a3} +#define PUSHARGS_4 stmfd sp!, {a1, a2, a3, a4} +#define PUSHARGS_5 stmfd sp!, {a1, a2, a3, a4} /* Caller has already pushed arg 5 */ +#define PUSHARGS_6 stmfd sp!, {a1, a2, a3, a4} + +#define POPARGS_1 add sp, sp, #4 +#define POPARGS_2 add sp, sp, #8 +#define POPARGS_3 add sp, sp, #12 +#define POPARGS_4 add sp, sp, #16 +#define POPARGS_5 add sp, sp, #16 +#define POPARGS_6 add sp, sp, #16 + +#ifndef NARGS +#define NARGS 3 /* If we were called with no wrapper, this is really socket() */ +#endif + +#if defined NEED_CANCELLATION && defined CENABLE + PSEUDO_PROLOGUE +#endif + +.globl __socket +ENTRY (__socket) + /* This code previously moved sp into ip and stored the args using + stmdb ip!, {a1-a4}. It did not modify sp, so the stack never had + to be restored after the syscall completed. It saved an + instruction and meant no stack cleanup work was required. + + This will not work in the case of a socket call being interrupted + by a signal. If the signal handler uses any stack the arguments + to socket will be trashed. The results of a restart of any + socket call are then unpredictable. */ + + /* Push args onto the stack. */ + P(PUSHARGS_,NARGS) + +#if defined NEED_CANCELLATION && defined CENABLE +#ifdef PIC + SINGLE_THREAD_P_PIC(r3) +#else + SINGLE_THREAD_P +#endif + bne 1f +#endif + + /* Do the system call trap. */ + mov a1, $P(SOCKOP_,socket) + mov a2, sp + swi SYS_ify(socketcall) + + /* Pop args off the stack */ + P(POPARGS_,NARGS) + + /* r0 is < 0 if there was an error. */ + cmn r0, $124 + RETINSTR(cc, r14) + b PLTJMP(SYSCALL_ERROR) + +#if defined NEED_CANCELLATION && defined CENABLE +1: + str lr, [sp, #-4]! + CENABLE + mov ip, r0 + + mov r0, #P(SOCKOP_,socket) + add r1, sp, #4 + swi SYS_ify(socketcall) + + str r0, [sp, #-4]! + mov r0, ip + CDISABLE + ldr r0, [sp], #4 + ldr lr, [sp], #4 + + P(POPARGS_,NARGS) + + /* r0 is < 0 if there was an error. */ + cmn r0, $124 + RETINSTR(cc, r14) + b PLTJMP(SYSCALL_ERROR) +#endif + +PSEUDO_END (__socket) + +weak_alias (__socket, socket) diff --git a/sysdeps/unix/sysv/linux/arm/sys/elf.h b/sysdeps/unix/sysv/linux/arm/sys/elf.h new file mode 100644 index 0000000000..faa7310682 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/sys/elf.h @@ -0,0 +1,26 @@ +/* Copyright (C) 1996, 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_ELF_H +#define _SYS_ELF_H 1 + +#warning "This header is obsolete; use <sys/procfs.h> instead." + +#include <sys/procfs.h> + +#endif /* sys/elf.h */ diff --git a/sysdeps/unix/sysv/linux/arm/sys/io.h b/sysdeps/unix/sysv/linux/arm/sys/io.h new file mode 100644 index 0000000000..68639902c7 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/sys/io.h @@ -0,0 +1,48 @@ +/* Copyright (C) 1996, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IO_H + +#define _SYS_IO_H 1 +#include <features.h> + +__BEGIN_DECLS + +/* If TURN_ON is TRUE, request for permission to do direct i/o on the + port numbers in the range [FROM,FROM+NUM-1]. Otherwise, turn I/O + permission off for that range. This call requires root privileges. */ +extern int ioperm (unsigned long int __from, unsigned long int __num, + int __turn_on) __THROW; + +/* Set the I/O privilege level to LEVEL. If LEVEL is nonzero, + permission to access any I/O port is granted. This call requires + root privileges. */ +extern int iopl (int __level) __THROW; + +/* The functions that actually perform reads and writes. */ +extern unsigned char inb (unsigned long int port) __THROW; +extern unsigned short int inw (unsigned long int port) __THROW; +extern unsigned long int inl (unsigned long int port) __THROW; + +extern void outb (unsigned char value, unsigned long int port) __THROW; +extern void outw (unsigned short value, unsigned long int port) __THROW; +extern void outl (unsigned long value, unsigned long int port) __THROW; + +__END_DECLS + +#endif /* _SYS_IO_H */ diff --git a/sysdeps/unix/sysv/linux/arm/sys/procfs.h b/sysdeps/unix/sysv/linux/arm/sys/procfs.h new file mode 100644 index 0000000000..3b3736324f --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/sys/procfs.h @@ -0,0 +1,123 @@ +/* Copyright (C) 1996, 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include <features.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/user.h> + +__BEGIN_DECLS + +/* Type for a general-purpose register. */ +typedef unsigned long elf_greg_t; + +/* And the whole bunch of them. We could have used `struct + user_regs' directly in the typedef, but tradition says that + the register set is an array, which does have some peculiar + semantics, so leave it that way. */ +#define ELF_NGREG (sizeof (struct user_regs) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* Register set for the floating-point registers. */ +typedef struct user_fpregs elf_fpregset_t; + +/* Signal info. */ +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with Linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + GDB doesn't really use excluded. */ + +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args. */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + +/* The rest of this file provides the types for emulation of the + Solaris <proc_service.h> interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/sysdeps/unix/sysv/linux/arm/sys/ucontext.h b/sysdeps/unix/sysv/linux/arm/sys/ucontext.h new file mode 100644 index 0000000000..6d6c8e3990 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/sys/ucontext.h @@ -0,0 +1,94 @@ +/* Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* System V/ARM ABI compliant context switching support. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include <features.h> +#include <signal.h> +#include <sys/procfs.h> + +typedef int greg_t; + +/* Number of general registers. */ +#define NGREG 16 + +/* Container for all general registers. */ +typedef elf_gregset_t gregset_t; + +/* Number of each register is the `gregset_t' array. */ +enum +{ + R0 = 0, +#define R0 R0 + R1 = 1, +#define R1 R1 + R2 = 2, +#define R2 R2 + R3 = 3, +#define R3 R3 + R4 = 4, +#define R4 R4 + R5 = 5, +#define R5 R5 + R6 = 6, +#define R6 R6 + R7 = 7, +#define R7 R7 + R8 = 8, +#define R8 R8 + R9 = 9, +#define R9 R9 + R10 = 10, +#define R10 R10 + R11 = 11, +#define R11 R11 + R12 = 12, +#define R12 R12 + R13 = 13, +#define R13 R13 + R14 = 14, +#define R14 R14 + R15 = 15 +#define R15 R15 +}; + +/* Structure to describe FPU registers. */ +typedef elf_fpregset_t fpregset_t; + +/* Context to describe whole processor state. */ +typedef struct + { + gregset_t gregs; + fpregset_t fpregs; + } mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + __sigset_t uc_sigmask; + stack_t uc_stack; + mcontext_t uc_mcontext; + long int uc_filler[5]; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/sysdeps/unix/sysv/linux/arm/sys/user.h b/sysdeps/unix/sysv/linux/arm/sys/user.h new file mode 100644 index 0000000000..3fae43f83f --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/sys/user.h @@ -0,0 +1,72 @@ +/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_USER_H +#define _SYS_USER_H 1 + +/* The whole purpose of this file is for GDB and GDB only. Don't read + too much into it. Don't use it for anything other than GDB unless + you know what you are doing. */ + +struct user_fpregs +{ + struct fp_reg + { + unsigned int sign1:1; + unsigned int unused:15; + unsigned int sign2:1; + unsigned int exponent:14; + unsigned int j:1; + unsigned int mantissa1:31; + unsigned int mantissa0:32; + } fpregs[8]; + unsigned int fpsr:32; + unsigned int fpcr:32; + unsigned char ftype[8]; + unsigned int init_flag; +}; + +struct user_regs +{ + unsigned long int uregs[18]; +}; + +struct user +{ + struct user_regs regs; /* General registers */ + int u_fpvalid; /* True if math co-processor being used. */ + + unsigned long int u_tsize; /* Text segment size (pages). */ + unsigned long int u_dsize; /* Data segment size (pages). */ + unsigned long int u_ssize; /* Stack segment size (pages). */ + + unsigned long start_code; /* Starting virtual address of text. */ + unsigned long start_stack; /* Starting virtual address of stack. */ + + long int signal; /* Signal that caused the core dump. */ + int reserved; /* No longer used */ + struct user_regs *u_ar0; /* help gdb to find the general registers. */ + + unsigned long magic; /* uniquely identify a core file */ + char u_comm[32]; /* User command that was responsible */ + int u_debugreg[8]; + struct user_fpregs u_fp; /* Floating point registers */ + struct user_fpregs *u_fp0; /* help gdb to find the FP registers. */ +}; + +#endif /* sys/user.h */ diff --git a/sysdeps/unix/sysv/linux/arm/syscalls.list b/sysdeps/unix/sysv/linux/arm/syscalls.list new file mode 100644 index 0000000000..1db0030b5b --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/syscalls.list @@ -0,0 +1,5 @@ +# File name Caller Syscall name # args Strong name Weak names + +syscall - syscall 7 syscall +oldgetrlimit EXTRA getrlimit i:ip __old_getrlimit getrlimit@GLIBC_2.0 +oldsetrlimit EXTRA setrlimit i:ip __old_setrlimit setrlimit@GLIBC_2.0 diff --git a/sysdeps/unix/sysv/linux/arm/sysdep.S b/sysdeps/unix/sysv/linux/arm/sysdep.S new file mode 100644 index 0000000000..1a4de2adb3 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/sysdep.S @@ -0,0 +1,34 @@ +/* Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> + + .text + +/* The syscall stubs jump here when they detect an error. + The code for Linux is almost identical to the canonical Unix + code, except that the error number in R0 is negated. */ + +#undef CALL_MCOUNT +#define CALL_MCOUNT /* Don't insert the profiling call, it clobbers R0. */ + +ENTRY (__syscall_error) + rsb r0, r0, $0 + +#define __syscall_error __syscall_error_1 +#include <sysdeps/unix/arm/sysdep.S> diff --git a/sysdeps/unix/sysv/linux/arm/sysdep.h b/sysdeps/unix/sysv/linux/arm/sysdep.h new file mode 100644 index 0000000000..668aa1a2f1 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/sysdep.h @@ -0,0 +1,236 @@ +/* Copyright (C) 1992, 93, 1995-2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>, August 1995. + ARM changes by Philip Blundell, <pjb27@cam.ac.uk>, May 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LINUX_ARM_SYSDEP_H +#define _LINUX_ARM_SYSDEP_H 1 + +/* There is some commonality. */ +#include <sysdeps/unix/arm/sysdep.h> + +/* For Linux we can use the system call table in the header file + /usr/include/asm/unistd.h + of the kernel. But these symbols do not follow the SYS_* syntax + so we have to redefine the `SYS_ify' macro here. */ +#undef SYS_ify +#define SWI_BASE (0x900000) +#define SYS_ify(syscall_name) (__NR_##syscall_name) + + +#ifdef __ASSEMBLER__ + +/* Linux uses a negative return value to indicate syscall errors, + unlike most Unices, which use the condition codes' carry flag. + + Since version 2.1 the return value of a system call might be + negative even if the call succeeded. E.g., the `lseek' system call + might return a large offset. Therefore we must not anymore test + for < 0, but test for a real error by making sure the value in R0 + is a real error number. Linus said he will make sure the no syscall + returns a value in -1 .. -4095 as a valid result so we can savely + test with -4095. */ + +#undef PSEUDO +#define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name); \ + DO_CALL (syscall_name, args); \ + cmn r0, $4096; + +#define PSEUDO_RET \ + RETINSTR(cc, lr); \ + b PLTJMP(SYSCALL_ERROR) +#undef ret +#define ret PSEUDO_RET + +#undef PSEUDO_END +#define PSEUDO_END(name) \ + SYSCALL_ERROR_HANDLER \ + END (name) + +#undef PSEUDO_NOERRNO +#define PSEUDO_NOERRNO(name, syscall_name, args) \ + .text; \ + ENTRY (name); \ + DO_CALL (syscall_name, args); + +#define PSEUDO_RET_NOERRNO \ + DO_RET (lr); + +#undef ret_NOERRNO +#define ret_NOERRNO PSEUDO_RET_NOERRNO + +#undef PSEUDO_END_NOERRNO +#define PSEUDO_END_NOERRNO(name) \ + END (name) + +/* The function has to return the error code. */ +#undef PSEUDO_ERRVAL +#define PSEUDO_ERRVAL(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + DO_CALL (syscall_name, args); \ + rsb r0, r0, #0 + +#undef PSEUDO_END_ERRVAL +#define PSEUDO_END_ERRVAL(name) \ + END (name) + +#define ret_ERRVAL PSEUDO_RET_NOERRNO + +#if NOT_IN_libc +# define SYSCALL_ERROR __local_syscall_error +# define SYSCALL_ERROR_HANDLER \ +__local_syscall_error: \ + str lr, [sp, #-4]!; \ + str r0, [sp, #-4]!; \ + bl PLTJMP(C_SYMBOL_NAME(__errno_location)); \ + ldr r1, [sp], #4; \ + rsb r1, r1, #0; \ + str r1, [r0]; \ + mvn r0, #0; \ + ldr pc, [sp], #4; +#else +# define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */ +# define SYSCALL_ERROR __syscall_error +#endif + +/* Linux takes system call args in registers: + syscall number in the SWI instruction + arg 1 r0 + arg 2 r1 + arg 3 r2 + arg 4 r3 + arg 5 r4 (this is different from the APCS convention) + arg 6 r5 + arg 7 r6 + + The compiler is going to form a call by coming here, through PSEUDO, with + arguments + syscall number in the DO_CALL macro + arg 1 r0 + arg 2 r1 + arg 3 r2 + arg 4 r3 + arg 5 [sp] + arg 6 [sp+4] + arg 7 [sp+8] + + We need to shuffle values between R4..R6 and the stack so that the + caller's v1..v3 and stack frame are not corrupted, and the kernel + sees the right arguments. + +*/ + +#undef DO_CALL +#define DO_CALL(syscall_name, args) \ + DOARGS_##args \ + swi SYS_ify (syscall_name); \ + UNDOARGS_##args + +#define DOARGS_0 /* nothing */ +#define DOARGS_1 /* nothing */ +#define DOARGS_2 /* nothing */ +#define DOARGS_3 /* nothing */ +#define DOARGS_4 /* nothing */ +#define DOARGS_5 str r4, [sp, $-4]!; ldr r4, [sp, $4]; +#define DOARGS_6 mov ip, sp; stmfd sp!, {r4, r5}; ldmia ip, {r4, r5}; +#define DOARGS_7 mov ip, sp; stmfd sp!, {r4, r5, r6}; ldmia ip, {r4, r5, r6}; + +#define UNDOARGS_0 /* nothing */ +#define UNDOARGS_1 /* nothing */ +#define UNDOARGS_2 /* nothing */ +#define UNDOARGS_3 /* nothing */ +#define UNDOARGS_4 /* nothing */ +#define UNDOARGS_5 ldr r4, [sp], $4; +#define UNDOARGS_6 ldmfd sp!, {r4, r5}; +#define UNDOARGS_7 ldmfd sp!, {r4, r5, r6}; + +#else /* not __ASSEMBLER__ */ + +/* Define a macro which expands into the inline wrapper code for a system + call. */ +#undef INLINE_SYSCALL +#define INLINE_SYSCALL(name, nr, args...) \ + ({ unsigned int _sys_result = INTERNAL_SYSCALL (name, , nr, args); \ + if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_sys_result, ), 0)) \ + { \ + __set_errno (INTERNAL_SYSCALL_ERRNO (_sys_result, )); \ + _sys_result = (unsigned int) -1; \ + } \ + (int) _sys_result; }) + +#undef INTERNAL_SYSCALL_DECL +#define INTERNAL_SYSCALL_DECL(err) do { } while (0) + +#undef INTERNAL_SYSCALL +#define INTERNAL_SYSCALL(name, err, nr, args...) \ + ({ unsigned int _sys_result; \ + { \ + register int _a1 asm ("a1"); \ + LOAD_ARGS_##nr (args) \ + asm volatile ("swi %1 @ syscall " #name \ + : "=r" (_a1) \ + : "i" (SYS_ify(name)) ASM_ARGS_##nr \ + : "memory"); \ + _sys_result = _a1; \ + } \ + (int) _sys_result; }) + +#undef INTERNAL_SYSCALL_ERROR_P +#define INTERNAL_SYSCALL_ERROR_P(val, err) \ + ((unsigned int) (val) >= 0xfffff001u) + +#undef INTERNAL_SYSCALL_ERRNO +#define INTERNAL_SYSCALL_ERRNO(val, err) (-(val)) + +#define LOAD_ARGS_0() +#define ASM_ARGS_0 +#define LOAD_ARGS_1(a1) \ + _a1 = (int) (a1); \ + LOAD_ARGS_0 () +#define ASM_ARGS_1 ASM_ARGS_0, "r" (_a1) +#define LOAD_ARGS_2(a1, a2) \ + register int _a2 asm ("a2") = (int) (a2); \ + LOAD_ARGS_1 (a1) +#define ASM_ARGS_2 ASM_ARGS_1, "r" (_a2) +#define LOAD_ARGS_3(a1, a2, a3) \ + register int _a3 asm ("a3") = (int) (a3); \ + LOAD_ARGS_2 (a1, a2) +#define ASM_ARGS_3 ASM_ARGS_2, "r" (_a3) +#define LOAD_ARGS_4(a1, a2, a3, a4) \ + register int _a4 asm ("a4") = (int) (a4); \ + LOAD_ARGS_3 (a1, a2, a3) +#define ASM_ARGS_4 ASM_ARGS_3, "r" (_a4) +#define LOAD_ARGS_5(a1, a2, a3, a4, a5) \ + register int _v1 asm ("v1") = (int) (a5); \ + LOAD_ARGS_4 (a1, a2, a3, a4) +#define ASM_ARGS_5 ASM_ARGS_4, "r" (_v1) +#define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6) \ + register int _v2 asm ("v2") = (int) (a6); \ + LOAD_ARGS_5 (a1, a2, a3, a4, a5) +#define ASM_ARGS_6 ASM_ARGS_5, "r" (_v2) +#define LOAD_ARGS_7(a1, a2, a3, a4, a5, a6, a7) \ + register int _v3 asm ("v3") = (int) (a7); \ + LOAD_ARGS_6 (a1, a2, a3, a4, a5, a6) +#define ASM_ARGS_7 ASM_ARGS_6, "r" (_v3) + +#endif /* __ASSEMBLER__ */ + +#endif /* linux/arm/sysdep.h */ diff --git a/sysdeps/unix/sysv/linux/arm/versionsort64.c b/sysdeps/unix/sysv/linux/arm/versionsort64.c new file mode 100644 index 0000000000..144b691e56 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/versionsort64.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/versionsort64.c> diff --git a/sysdeps/unix/sysv/linux/arm/vfork.S b/sysdeps/unix/sysv/linux/arm/vfork.S new file mode 100644 index 0000000000..9ef5114b24 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/vfork.S @@ -0,0 +1,59 @@ +/* Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell <philb@gnu.org>. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#define _ERRNO_H 1 +#include <bits/errno.h> +#include <kernel-features.h> + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + +#ifdef __NR_vfork + swi __NR_vfork + cmn a1, #4096 + RETINSTR(cc, lr) + +# ifdef __ASSUME_VFORK_SYSCALL + b PLTJMP(C_SYMBOL_NAME(__syscall_error)) +# else + /* Check if vfork syscall is known at all. */ + cmn a2, #ENOSYS + bne PLTJMP(C_SYMBOL_NAME(__syscall_error)) +# endif +#endif + +#ifndef __ASSUME_VFORK_SYSCALL + /* If we don't have vfork, fork is close enough. */ + swi __NR_fork + cmn a1, #4096 + RETINSTR(cc, lr) + b PLTJMP(C_SYMBOL_NAME(__syscall_error)) +#elif !defined __NR_vfork +# error "__NR_vfork not available and __ASSUME_VFORK_SYSCALL defined" +#endif + +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/sysdeps/unix/sysv/linux/arm/xstat.c b/sysdeps/unix/sysv/linux/arm/xstat.c new file mode 100644 index 0000000000..e9869f5508 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/xstat.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/xstat.c> |