diff options
Diffstat (limited to 'klibc/klibc')
360 files changed, 18170 insertions, 0 deletions
diff --git a/klibc/klibc/CAVEATS b/klibc/klibc/CAVEATS new file mode 100644 index 0000000000..c7131ac367 --- /dev/null +++ b/klibc/klibc/CAVEATS @@ -0,0 +1,51 @@ + ------------------------------------------------- + Please note the following caveats to using klibc: + ------------------------------------------------- + +optimization: +------------- + +Compiling with -O0 is not supported. It may or may not work; please +use -O1 if you want to do maximize debuggability. + +Compiling with -O0 is more likely to work on gcc 3. + + +setjmp()/longjmp(): +------------------- + +setjmp() and longjmp() *do not* save signal state. sigsetjmp() and +siglongjmp() *do* save the signal mask -- regardless of the value of +the extra argument. + +The standards actually state that if you pass longjmp() a final value +of zero the library should change that to a 1! Presumably the reason +is so people who write broken code can get away with writing +longjmp(buf); or something equally bad. If you pass longjmp() a final +value of 0 you get what you deserve -- setjmp() will happily return 0. + + +stdio: +------ + +Only a small subset of the stdio functions are implemented. Those +that are implemented do not buffer, although they *do* trap EINTR or +short read/writes and iterate. + +_fread() and _fwrite(), which take only one size argument (like +read/write), but do handle EINTR/short return are also available. + + +namespaces: +----------- + +klibc frequently includes headers in other headers in a way that +exposes more symbols than POSIX says they should. "Live with it." + + +theading: +--------- + +klibc is not thread-safe. Consequently, clone() or any of the +pthreads functions are not included. + diff --git a/klibc/klibc/LICENSE b/klibc/klibc/LICENSE new file mode 100644 index 0000000000..b512ff96bc --- /dev/null +++ b/klibc/klibc/LICENSE @@ -0,0 +1,73 @@ +This license applies to all files in directory and its subdirectories, +unless otherwise noted in individual files. + + +Some files are derived from files derived from the include/ directory +of the Linux kernel, and are licensed under the terms of the GNU +General Public License, version 2, as released by the Free Software +Foundation, Inc.; incorporated herein by reference. + + ----- + +Some files are derived from files copyrighted by the Regents of The +University of California, and are available under the following +license: + +Note: The advertising clause in the license appearing on BSD Unix +files was officially rescinded by the Director of the Office of +Technology Licensing of the University of California on July 22 +1999. He states that clause 3 is "hereby deleted in its entirety." + + * Copyright (c) + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + + ----- + +For all remaining files, the following license applies: + + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * Any copyright notice(s) and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/klibc/klibc/MCONFIG b/klibc/klibc/MCONFIG new file mode 100644 index 0000000000..a46a98a9dd --- /dev/null +++ b/klibc/klibc/MCONFIG @@ -0,0 +1,49 @@ +# -*- makefile -*- +# +# Makefile configuration, without explicit rules +# + +SRCROOT = .. +include ../MCONFIG + +WARNFLAGS = -W -Wall -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Winline +CFLAGS = -Wp,-MD,$(dir $*).$(notdir $*).d $(OPTFLAGS) $(REQFLAGS) $(WARNFLAGS) + +SOFLAGS = -fPIC + +.SUFFIXES: .c .o .a .so .lo .i .S .s .ls .ss .lss + +.c.o: + $(CC) $(CFLAGS) -c -o $@ $< + +.c.i: + $(CC) $(CFLAGS) -E -o $@ $< + +.c.s: + $(CC) $(CFLAGS) -S -o $@ $< + +.S.o: + $(CC) $(CFLAGS) -D__ASSEMBLY__ -c -o $@ $< + +.S.s: + $(CC) $(CFLAGS) -D__ASSEMBLY__ -E -o $@ $< + +.S.lo: + $(CC) $(CFLAGS) $(SOFLAGS) -D__ASSEMBLY__ -c -o $@ $< + +.S.ls: + $(CC) $(CFLAGS) $(SOFLAGS) -D__ASSEMBLY__ -E -o $@ $< + +.s.o: + $(CC) $(CFLAGS) -x assembler -c -o $@ $< + +.ls.lo: + $(CC) $(CFLAGS) $(SOFLAGS) -x assembler -c -o $@ $< + +.c.lo: + $(CC) $(CFLAGS) $(SOFLAGS) -c -o $@ $< + +.c.ls: + $(CC) $(CFLAGS) $(SOFLAGS) -S -o $@ $< + + diff --git a/klibc/klibc/Makefile b/klibc/klibc/Makefile new file mode 100644 index 0000000000..470a276ded --- /dev/null +++ b/klibc/klibc/Makefile @@ -0,0 +1,135 @@ +# +# Makefile +# +# Main makefile +# + +# Include configuration rules +include MCONFIG + +TESTS = $(patsubst %.c,%,$(wildcard tests/*.c)) \ + $(patsubst %.c,%.shared,$(wildcard tests/*.c)) +LIBOBJS = vsnprintf.o snprintf.o vsprintf.o sprintf.o \ + vsscanf.o sscanf.o ctypes.o \ + strntoumax.o strntoimax.o \ + atoi.o atol.o atoll.o \ + strtol.o strtoll.o strtoul.o strtoull.o \ + strtoimax.o strtoumax.o \ + globals.o exitc.o atexit.o onexit.o \ + execl.o execle.o execv.o execvpe.o execvp.o execlp.o execlpe.o \ + fork.o wait.o wait3.o waitpid.o system.o setpgrp.o \ + printf.o vprintf.o fprintf.o vfprintf.o perror.o \ + fopen.o fread.o fread2.o fgetc.o fgets.o \ + fwrite.o fwrite2.o fputc.o fputs.o puts.o \ + sleep.o usleep.o raise.o abort.o assert.o alarm.o pause.o \ + __signal.o signal.o bsd_signal.o siglist.o siglongjmp.o \ + sigaction.o sigpending.o sigprocmask.o sigsuspend.o \ + brk.o sbrk.o malloc.o realloc.o calloc.o mmap.o \ + memcpy.o memcmp.o memset.o memccpy.o memmem.o memswap.o \ + memmove.o \ + strcat.o strchr.o strcmp.o strcpy.o strdup.o strlen.o \ + strncat.o strstr.o strncmp.o strncpy.o strrchr.o strspn.o \ + strsep.o strtok.o \ + gethostname.o getdomainname.o getcwd.o \ + seteuid.o setegid.o setresuid.o setresgid.o \ + getenv.o setenv.o unsetenv.o getopt.o readdir.o \ + syslog.o closelog.o pty.o isatty.o reboot.o \ + time.o utime.o fdatasync.o llseek.o select.o nice.o getpriority.o \ + qsort.o lrand48.o srand48.o seed48.o \ + inet/inet_ntoa.o inet/inet_aton.o inet/inet_addr.o \ + inet/inet_ntop.o inet/inet_pton.o inet/bindresvport.o \ + send.o recv.o +SOLIB = libc.so +SOHASH = klibc.so + +CRT0 = crt0.o +LIB = libc.a + +#all: tests $(CRT0) $(LIB) $(SOLIB) klibc.so +all: $(CRT0) $(LIB) $(SOLIB) klibc.so + +# Add any architecture-specific rules +include arch/$(ARCH)/Makefile.inc + +tests: $(TESTS) + +tests/%.o : tests/%.c + $(CC) $(CFLAGS) -c -o $@ $< + +tests/% : tests/%.o $(LIB) $(CRT0) + $(LD) $(LDFLAGS) -o $@ $(CRT0) $< $(LIB) $(LIBGCC) + cp $@ $@.stripped + $(STRIP) $@.stripped + +tests/%.shared : tests/%.o interp.o $(SOLIB) + $(LD) $(LDFLAGS) -o $@ -e main interp.o tests/$*.o -R $(SOLIB) $(LIBGCC) + cp $@ $@.stripped + $(STRIP) $@.stripped + +$(LIB): __static_init.o $(LIBOBJS) $(ARCHOBJS) syscalls/static.obj socketcalls/static.obj + rm -f $(LIB) + $(AR) cq $(LIB) __static_init.o $(LIBOBJS) $(ARCHOBJS) syscalls/*.o socketcalls/*.o + $(RANLIB) $(LIB) + +$(SOLIB): $(CRT0) __shared_init.o $(LIBOBJS) $(ARCHOBJS) syscalls/static.obj socketcalls/static.obj + $(LD) $(LDFLAGS) $(SHAREDFLAGS) -o $@ \ + $(CRT0) __shared_init.o $(LIBOBJS) $(ARCHOBJS) \ + syscalls/*.o socketcalls/*.o \ + $(LIBGCC) + +sha1hash: sha1hash.c + $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ $< + +$(SOLIB).hash: $(SOLIB) sha1hash + $(NM) $(SOLIB) | \ + egrep '^[0-9a-fA-F]+ [ADRTW] ' | sort | ./sha1hash > $@ + +$(SOHASH): $(SOLIB) $(SOLIB).hash + cp -f $(SOLIB) $@ + $(STRIP) $@ + rm -f klibc-??????????????????????.so + ln -f $@ klibc-`cat $(SOLIB).hash`.so + +interp.o: interp.S $(SOLIB).hash + $(CC) $(CFLAGS) -D__ASSEMBLY__ -DLIBDIR=\"$(SHLIBDIR)\" \ + -DSOHASH=\"`cat $(SOLIB).hash`\" \ + -c -o $@ $< + +crt0.o: arch/$(ARCH)/crt0.o + cp arch/$(ARCH)/crt0.o . + +syscalls.dir: SYSCALLS syscalls.pl syscommon.h + rm -rf syscalls + mkdir syscalls + $(PERL) syscalls.pl $(ARCH) SYSCALLS + touch $@ + +socketcalls.dir: SOCKETCALLS socketcalls.pl socketcommon.h + rm -rf socketcalls + mkdir socketcalls + $(PERL) socketcalls.pl $(ARCH) SOCKETCALLS + touch $@ + +%/static.obj: %.dir + $(MAKE) objects-$(basename $(notdir $@)) DIR=$* + +STATIC = $(addsuffix .o,$(basename $(wildcard $(DIR)/*.[cS]))) + +objects-static: $(STATIC) + touch $(DIR)/static.obj + +clean: archclean + find . -type f -a \( -name \*.[isoa] -o -name \*.l[iso] \) -print0 | xargs -0rt rm -f + rm -f *.a *.so *.hash *.syms *.stripped + rm -f $(TESTS) tests/*.stripped + rm -rf syscalls syscalls.dir + rm -rf socketcalls socketcalls.dir + rm -f sha1hash + +spotless: clean + find . \( -name \*~ -o -name '.*.d' \) -not -type d -print0 | \ + xargs -0rt rm -f + +ifneq ($(wildcard $(DIR)/.*.d),) +include $(wildcard $(DIR)/.*.d) +endif diff --git a/klibc/klibc/README b/klibc/klibc/README new file mode 100644 index 0000000000..7d5751804f --- /dev/null +++ b/klibc/klibc/README @@ -0,0 +1,57 @@ +This is klibc, what is intended to be a minimalistic libc subset for +use with initramfs. It is deliberately written for small size, +minimal entaglement and portability, not speed. It is definitely a +work in progress, and a lot of things are still missing. + + +The build procedure is not very polished yet, but it should work like +this: + +a) In the source root directory (the directory above the one in which + this file is found) create a symlink called "linux" pointing to a + reasonably recent Linux kernel tree (2.4 or 2.5 should be OK.) + This tree must have the include/asm symlink set up for the + architecture you're compiling for, and include/linux/autoconf.h + must exist. The easiest way to make sure of all of these is to do + a "make config" or any of its variants on the kernel tree is + question, followed by a "make dep". + +b) If you're cross-compiling, change ARCH in the main MCONFIG file to + the appropriate architecture, and set CROSS to your toolchain + prefix. + + IMPORTANT: if you're on a 64-bit machine with a 32-bit userland + (ia64, mips64, ppc64 sparc64, s390x or x86_64), and you want to + build the 32-bit version: you need to set ARCH to the 32-bit + architecture as well as set up the linux/include/asm symlink to + point to the 32-bit architecture. Building the 32-bit architecture + usually (but not always) produces smaller binaries, and is likely + to be better tested. + + If you are on ARM, and want to build a thumb version of the library + (this is supported), change OPTFLAGS in arch/arm/MCONFIG to build + thumb code. + + The following is the last known status of various architectures: + + Known to work: alpha arm i386 s390 s390x sparc sparc64 x86_64* + Works static, not shared: mips* arm-thumb sh* + Need crt0.S updates: ppc + Missing setjmp: ppc64 + Need porting work: cris ia64 m68k mips64 parisc + + x86_64: requires a kernel header patch (to be created) + mips, sh: linker problem; might work with fixed linker + + Shared library support for sparc/sparc64 requires binutils 2.13.90.0.4. + + Note that even the "known to work" ones likely have bugs. Please + report them if you run into them. + +c) Type "make" and pray... + +d) Try the test programs in the tests/ directory. They should run... + +Contact me at <hpa@zytor.com> for more info. + + -hpa diff --git a/klibc/klibc/SOCKETCALLS b/klibc/klibc/SOCKETCALLS new file mode 100644 index 0000000000..1ab4e367a2 --- /dev/null +++ b/klibc/klibc/SOCKETCALLS @@ -0,0 +1,21 @@ +# -*- fundamental -*- +# +# These are calls that are invoked via the socketcall mechanism +# +int socket(int, int, int) +int bind(int, struct sockaddr *, int) +int connect(int, struct sockaddr *, socklen_t) +int listen(int, int) +int accept(int, struct sockaddr *, socklen_t *) +int getsockname(int, struct sockaddr *, socklen_t *) +int getpeername(int, struct sockaddr *, socklen_t *) +int socketpair(int, int, int, int *) +# int send(int, const void *, size_t, unsigned int) +int sendto(int, const void *, size_t, int, const struct sockaddr *, socklen_t) +# int recv(int, void *, size_t, unsigned int) +int recvfrom(int, void *, size_t, unsigned int, struct sockaddr *, socklen_t *) +int shutdown(int, int) +int setsockopt(int, int, int, const void *, socklen_t) +int getsockopt(int, int, int, void *, socklen_t *) +int sendmsg(int, const struct msghdr *, unsigned int) +int recvmsg(int, struct msghdr *, unsigned int) diff --git a/klibc/klibc/SYSCALLS b/klibc/klibc/SYSCALLS new file mode 100644 index 0000000000..1ec94acec6 --- /dev/null +++ b/klibc/klibc/SYSCALLS @@ -0,0 +1,146 @@ +# -*- fundamental -*- +# +# This is a list of system calls we invoke "directly". These +# are generated into syscall stubs in their own C files, so the +# linker can do its job properly. +# +# The full description of a line is: +# [<[!]arch,...>] type sysname[@systype][::funcname](args) +# + +# +# Process-related syscalls +# +<!mips,mips64,sparc> pid_t vfork() +<sparc> pid_t vfork@forkish() +<!alpha> pid_t getpid() +<alpha> pid_t getxpid@dual0::getpid() +int setpgid(pid_t, pid_t) +pid_t getpgid(pid_t) +<!alpha> pid_t getppid() +<alpha> pid_t getxpid@dual1::getppid() +<!ia64> pid_t getpgrp() +pid_t setsid() +pid_t getsid(pid_t) +pid_t wait4(pid_t, int *, int, struct rusage *) +int execve(const char *, char * const *, char * const *) +int setpriority(int, int, int) +int sched_setscheduler(pid_t, int, const struct sched_param *) +int sched_yield() + +# +# User and group IDs +# +int setuid(uid_t) +int setgid(gid_t) +<!alpha> uid_t getuid() +<alpha> uid_t getxuid@dual0::getuid() +<!alpha> gid_t getgid() +<alpha> gid_t getxgid@dual0::getgid() +<!alpha> uid_t geteuid() +<alpha> uid_t getxuid@dual1::geteuid() +<!alpha> gid_t getegid() +<alpha> uid_t getxgid@dual1::getegid() +int getgroups(int, gid_t *) +int setgroups(size_t, const gid_t *) +int setreuid(uid_t, uid_t) +int setregid(gid_t, gid_t) +int setfsuid(uid_t) +int setfsgid(gid_t) + +# +# Filesystem-related system calls +# +int mount(const char *, const char *, const char *, unsigned long, const void *) +<!alpha,ia64> int umount2(const char *, int) +<alpha,ia64> int umount::umount2(const char *, int) +<!m68k> int pivot_root(const char *, const char *) +int sync() +int statfs(const char *, struct statfs *) +int fstatfs(int, struct statfs *) +int swapon(const char *, int) +int swapoff(const char *) + +# +# Inode-related system calls +# +int access(const char *, int) +int link(const char *, const char *) +int unlink(const char *) +int chdir(const char *) +int rename(const char *, const char *) +int mknod(const char *, mode_t, dev_t) +int chmod(const char *, mode_t) +int mkdir(const char *, mode_t) +int rmdir(const char *) +<!alpha,mips,mips64> int pipe(int *) +mode_t umask(mode_t) +int chroot(const char *) +int symlink(const char *, const char *) +int readlink(const char *, char *, size_t) +int stat(const char *, struct stat *) +int lstat(const char *, struct stat *) +int fstat(int, struct stat *) +int getdents(unsigned int, struct dirent *, unsigned int) +int chown(const char *, uid_t, gid_t) +int fchown(int, uid_t, gid_t) +int lchown(const char *, uid_t, gid_t) + +# +# I/O operations +# +ssize_t read(int, void *, size_t) +ssize_t write(int, const void *, size_t) +int open(const char *, int, mode_t) +int close(int) +off_t lseek(int, off_t, int) +int dup(int) +int dup2(int, int) +int fcntl(int, int, long) +int ioctl(int, int, void *) +int flock(int, int) +int poll(struct pollfd *, nfds_t, long) +int fsync(int) +int readv(int, const struct iovec *, int) +int writev(int, const struct iovec *, int) + +# +# Signal operations +# +int kill(pid_t, int) +int rt_sigaction(int, const struct sigaction *, struct sigaction *, size_t) +int rt_sigsuspend(const sigset_t *, size_t) +int rt_sigpending(sigset_t *, size_t) +int rt_sigprocmask(int, const sigset_t *, sigset_t *, size_t) +int getitimer(int, struct itimerval *) +int setitimer(int, const struct itimerval *, struct itimerval *) + +# +# Time-related system calls +# +clock_t times(struct tms *) +int gettimeofday(struct timeval *, struct timezone *) +int settimeofday(const struct timeval *, const struct timezone *) +int nanosleep(const struct timespec *, struct timespec *) + +# +# Memory +# +void * brk::__brk(void *) +int munmap(void *, size_t) +void * mremap(void *, size_t, size_t, unsigned long) +int msync(const void *, size_t, int) +int mprotect(const void *, size_t, int) + +# +# System stuff +# +int uname(struct utsname *) +int setdomainname(const char *, size_t) +int sethostname(const char *, size_t) +int init_module(const char *, struct module *) +void * create_module(const char *, size_t) +int delete_module(const char *) +int query_module(const char *, int, void *, size_t, size_t) +int reboot::__reboot(int, int, int, void *) +int syslog::klogctl(int, char *, int) diff --git a/klibc/klibc/__shared_init.c b/klibc/klibc/__shared_init.c new file mode 100644 index 0000000000..63e3f4644e --- /dev/null +++ b/klibc/klibc/__shared_init.c @@ -0,0 +1,56 @@ +/* + * __shared_init.c + * + * This function takes the raw data block set up by the ELF loader + * in the kernel and parses it. It is invoked by crt0.S which makes + * any necessary adjustments and passes calls this function using + * the standard C calling convention. + * + * The arguments are: + * uintptr_t *elfdata -- The ELF loader data block; usually from the stack. + * Basically a pointer to argc. + * void (*onexit)(void) -- Function to install into onexit + */ + +#include <stddef.h> +#include <stdlib.h> +#include <stdint.h> +#include <klibc/compiler.h> +#include <elf.h> + +char **environ; + +__noreturn __libc_init(uintptr_t *elfdata, void (*onexit)(void)) +{ + int argc; + char **argv, **envp, **envend; + struct auxentry { + uintptr_t type; + uintptr_t v; + } *auxentry; + typedef int (*main_t)(int, char **, char **); + main_t main_ptr = NULL; + + (void)onexit; /* For now, we ignore this... */ + + argc = (int)*elfdata++; + argv = (char **)elfdata; + envp = argv+(argc+1); + + /* The auxillary entry vector is after all the environment vars */ + for ( envend = envp ; *envend ; envend++ ); + auxentry = (struct auxentry *)(envend+1); + + while ( auxentry->type ) { + if ( auxentry->type == AT_ENTRY ) { + main_ptr = (main_t)(auxentry->v); + break; + } + auxentry++; + } + + environ = envp; + exit(main_ptr(argc, argv, envp)); +} + + diff --git a/klibc/klibc/__signal.c b/klibc/klibc/__signal.c new file mode 100644 index 0000000000..b5081d386b --- /dev/null +++ b/klibc/klibc/__signal.c @@ -0,0 +1,22 @@ +/* + * __signal.c + */ + +#include <signal.h> + +__sighandler_t __signal(int signum, __sighandler_t handler, int flags) +{ + struct sigaction sa; + + sa.sa_handler = handler; + sa.sa_flags = flags; + sigemptyset(&sa.sa_mask); + + if ( sigaction(signum, &sa, &sa) ) { + return (__sighandler_t)SIG_ERR; + } else { + return (__sighandler_t)sa.sa_handler; + } +} + + diff --git a/klibc/klibc/__static_init.c b/klibc/klibc/__static_init.c new file mode 100644 index 0000000000..dcb8d01856 --- /dev/null +++ b/klibc/klibc/__static_init.c @@ -0,0 +1,40 @@ +/* + * __static_init.c + * + * This function takes the raw data block set up by the ELF loader + * in the kernel and parses it. It is invoked by crt0.S which makes + * any necessary adjustments and passes calls this function using + * the standard C calling convention. + * + * The arguments are: + * uintptr_t *elfdata -- The ELF loader data block; usually from the stack. + * Basically a pointer to argc. + * void (*onexit)(void) -- Function to install into onexit + */ + +#include <stddef.h> +#include <stdlib.h> +#include <stdint.h> +#include <klibc/compiler.h> +#include <elf.h> + +char **environ; + +extern int main(int, char **, char **); + +__noreturn __libc_init(uintptr_t *elfdata, void (*onexit)(void)) +{ + int argc; + char **argv, **envp; + + (void)onexit; /* For now, we ignore this... */ + + argc = (int)*elfdata++; + argv = (char **)elfdata; + envp = argv+(argc+1); + + environ = envp; + exit(main(argc, argv, envp)); +} + + diff --git a/klibc/klibc/abort.c b/klibc/klibc/abort.c new file mode 100644 index 0000000000..9280d9861b --- /dev/null +++ b/klibc/klibc/abort.c @@ -0,0 +1,19 @@ +/* + * abort.c + */ + +#include <stdlib.h> +#include <unistd.h> +#include <signal.h> + +void abort(void) +{ + sigset_t set; + + sigemptyset(&set); + sigaddset(&set, SIGABRT); + sigprocmask(SIG_UNBLOCK, &set, NULL); + raise(SIGABRT); + _exit(255); /* raise() should have killed us */ +} + diff --git a/klibc/klibc/alarm.c b/klibc/klibc/alarm.c new file mode 100644 index 0000000000..ca7bb37f92 --- /dev/null +++ b/klibc/klibc/alarm.c @@ -0,0 +1,29 @@ +/* + * alarm.c + */ + +#include <sys/time.h> +#include <sys/syscall.h> + +#ifdef __NR_alarm + +_syscall1(unsigned int,alarm,unsigned int,seconds); + +#else + +/* Emulate alarm() via setitimer() */ + +unsigned int alarm(unsigned int seconds) +{ + struct itimerval iv; + + iv.it_interval.tv_sec = iv.it_interval.tv_usec = 0; + iv.it_value.tv_sec = seconds; + iv.it_value.tv_usec = 0; + + setitimer(ITIMER_REAL, &iv, &iv); + + return iv.it_value.tv_sec + (iv.it_value.tv_usec ? 1 : 0); +} + +#endif diff --git a/klibc/klibc/arch/README b/klibc/klibc/arch/README new file mode 100644 index 0000000000..eceb23de4b --- /dev/null +++ b/klibc/klibc/arch/README @@ -0,0 +1,67 @@ +To port klibc to a new architecture, you need: + +a) A directory structure + +Each archtecture has an arch/ directory, which should include an +MCONFIG and a Makefile.inc file. + +b) Startup code (arch/*/crt0.S) + +The crt0.S assembly routine typically corresponds to the following +pseudo-C code. In addition, each architecture needs any support +routines that gcc-generated code expects to find in the system library +-- Alpha, for example, needs divide subroutines. + +The "getenvtest" test program is a very good test for proper crt0.S +functionality. + + +extern __noreturn __libc_init(void *, void *); + +__noreturn _start(void) +{ + void *elf_data = get_elf_data_address(); /* Usually the stack address */ + void *atexit_ptr = get_atexit_ptr(); /* Usually in a register */ + + /* Some architectures need this for debugging to work */ + setup_null_stack_frame_if_necessary(); + + __libc_init(elf_data, atexit_ptr); +} + + +c) A setenv implementation (arch/*/setjmp.S, arch/*/include/klibc/archsetjmp.h) + +On most (but not all!) architectures, this entails creating a setjmp +buffer big enough to hold all callee-saved registers, plus the stack +pointer and the return address. In setjmp.S you have: + +* A "setjmp" function that writes out the callee-saved registers, the + stack pointer and the return address to the buffer pointed to by the + first argument, and then returns zero normally. + + On some architectures you need to take some kind of action to make + sure the contents of the stack is actually manifest in memory and + not cached in the CPU. In some cases (e.g. on SPARC) this will + automatically spill the registers onto the stack; then they don't + need to be spilled into the jmp_buf. + +* A "longjmp" function that read back these same registers from the + jmp_buf pointed to by the first argument, and returns the second + argument *to the address specified in the jmp_buf*. + + On some architectures you need to take some kind of action to flush + any cached stack data or return stack. + + +d) Any support functions needed by gcc, *unless* they are in libgcc + *and* libgcc is usable for klibc on your particular platform. If + libgcc isn't usable for klibc (on MIPS, for example, libgcc is + compiled in a way that is not compatible with klibc) there are + reasonably good clones of most of the libgcc functions in the libgcc + directory. To use them, add them to ARCHOBJS in + arch/*/Makefile.inc. + + +e) A link location for the shared klibc. This should be specified in + SHAREDFLAGS in arch/*/MCONFIG. diff --git a/klibc/klibc/arch/alpha/MCONFIG b/klibc/klibc/arch/alpha/MCONFIG new file mode 100644 index 0000000000..5987ed5841 --- /dev/null +++ b/klibc/klibc/arch/alpha/MCONFIG @@ -0,0 +1,17 @@ +# -*- makefile -*- +# +# arch/alpha/MCONFIG +# +# Build configuration for this architecture +# + +OPTFLAGS = -Os -fomit-frame-pointer +BITSIZE = 64 + +# Extra linkflags when building the shared version of the library +# This address needs to be reachable using normal inter-module +# calls, and work on the memory models for this architecture +# 7 GB - normal binaries start at 4.5 GB, and the stack is below +# the binary. +SHAREDFLAGS = -Ttext 0x1c0000200 + diff --git a/klibc/klibc/arch/alpha/Makefile.inc b/klibc/klibc/arch/alpha/Makefile.inc new file mode 100644 index 0000000000..2a1100f962 --- /dev/null +++ b/klibc/klibc/arch/alpha/Makefile.inc @@ -0,0 +1,93 @@ +# -*- makefile -*- +# +# arch/alpha/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +# Special CFLAGS for the divide code +DIVCFLAGS = $(REQFLAGS) \ + -O3 -fomit-frame-pointer -fcall-saved-1 -fcall-saved-2 \ + -fcall-saved-3 -fcall-saved-4 -fcall-saved-5 -fcall-saved-6 \ + -fcall-saved-7 -fcall-saved-8 -fcall-saved-15 -fcall-saved-16 \ + -fcall-saved-17 -fcall-saved-18 -fcall-saved-19 -fcall-saved-20 \ + -fcall-saved-21 -fcall-saved-22 -ffixed-23 -fcall-saved-24 \ + -ffixed-25 -ffixed-27 + +ARCHOBJS = \ + arch/$(ARCH)/__divqu.o \ + arch/$(ARCH)/__remqu.o \ + arch/$(ARCH)/__divq.o \ + arch/$(ARCH)/__remq.o \ + arch/$(ARCH)/__divlu.o \ + arch/$(ARCH)/__remlu.o \ + arch/$(ARCH)/__divl.o \ + arch/$(ARCH)/__reml.o \ + arch/$(ARCH)/pipe.o \ + arch/$(ARCH)/setjmp.o + +ARCHSOOBJS = $(patsubst %.o,%.lo,$(ARCHOBJS)) + +arch/$(ARCH)/%.s: arch/$(ARCH)/%.ss + sed -e 's/\$$0\b/$$27/g' -e 's/\$$24\b/$$99/g' \ + -e 's/\$$16\b/$$24/g' -e 's/\$$17\b/$$25/g' \ + -e 's/\$$26\b/$$23/g' -e 's/\$$99\b/$$16/g' < $< > $@ + +arch/$(ARCH)/%.ls: arch/$(ARCH)/%.lss + sed -e 's/\$$0\b/$$27/g' -e 's/\$$24\b/$$99/g' \ + -e 's/\$$16\b/$$24/g' -e 's/\$$17\b/$$25/g' \ + -e 's/\$$26\b/$$23/g' -e 's/\$$99\b/$$16/g' < $< > $@ + +arch/$(ARCH)/__divqu.ss: arch/$(ARCH)/divide.c + $(CC) $(DIVCFLAGS) -DSIGNED=0 -DREM=0 -DBITS=64 -DNAME=__divqu -S -o $@ $< + +arch/$(ARCH)/__remqu.ss: arch/$(ARCH)/divide.c + $(CC) $(DIVCFLAGS) -DSIGNED=0 -DREM=1 -DBITS=64 -DNAME=__remqu -S -o $@ $< + +arch/$(ARCH)/__divq.ss: arch/$(ARCH)/divide.c + $(CC) $(DIVCFLAGS) -DSIGNED=1 -DREM=0 -DBITS=64 -DNAME=__divq -S -o $@ $< + +arch/$(ARCH)/__remq.ss: arch/$(ARCH)/divide.c + $(CC) $(DIVCFLAGS) -DSIGNED=1 -DREM=1 -DBITS=64 -DNAME=__remq -S -o $@ $< + +arch/$(ARCH)/__divlu.ss: arch/$(ARCH)/divide.c + $(CC) $(DIVCFLAGS) -DSIGNED=0 -DREM=0 -DBITS=32 -DNAME=__divlu -S -o $@ $< + +arch/$(ARCH)/__remlu.ss: arch/$(ARCH)/divide.c + $(CC) $(DIVCFLAGS) -DSIGNED=0 -DREM=1 -DBITS=32 -DNAME=__remlu -S -o $@ $< + +arch/$(ARCH)/__divl.ss: arch/$(ARCH)/divide.c + $(CC) $(DIVCFLAGS) -DSIGNED=1 -DREM=0 -DBITS=32 -DNAME=__divl -S -o $@ $< + +arch/$(ARCH)/__reml.ss: arch/$(ARCH)/divide.c + $(CC) $(DIVCFLAGS) -DSIGNED=1 -DREM=1 -DBITS=32 -DNAME=__reml -S -o $@ $< + +arch/$(ARCH)/__divqu.lss: arch/$(ARCH)/divide.c + $(CC) $(DIVCFLAGS) -fPIC -DSIGNED=0 -DREM=0 -DBITS=64 -DNAME=__divqu -S -o $@ $< + +arch/$(ARCH)/__remqu.lss: arch/$(ARCH)/divide.c + $(CC) $(DIVCFLAGS) -fPIC -DSIGNED=0 -DREM=1 -DBITS=64 -DNAME=__remqu -S -o $@ $< + +arch/$(ARCH)/__divq.lss: arch/$(ARCH)/divide.c + $(CC) $(DIVCFLAGS) -fPIC -DSIGNED=1 -DREM=0 -DBITS=64 -DNAME=__divq -S -o $@ $< + +arch/$(ARCH)/__remq.lss: arch/$(ARCH)/divide.c + $(CC) $(DIVCFLAGS) -fPIC -DSIGNED=1 -DREM=1 -DBITS=64 -DNAME=__remq -S -o $@ $< + +arch/$(ARCH)/__divlu.lss: arch/$(ARCH)/divide.c + $(CC) $(DIVCFLAGS) -fPIC -DSIGNED=0 -DREM=0 -DBITS=32 -DNAME=__divlu -S -o $@ $< + +arch/$(ARCH)/__remlu.lss: arch/$(ARCH)/divide.c + $(CC) $(DIVCFLAGS) -fPIC -DSIGNED=0 -DREM=1 -DBITS=32 -DNAME=__remlu -S -o $@ $< + +arch/$(ARCH)/__divl.lss: arch/$(ARCH)/divide.c + $(CC) $(DIVCFLAGS) -fPIC -DSIGNED=1 -DREM=0 -DBITS=32 -DNAME=__divl -S -o $@ $< + +arch/$(ARCH)/__reml.lss: arch/$(ARCH)/divide.c + $(CC) $(DIVCFLAGS) -fPIC -DSIGNED=1 -DREM=1 -DBITS=32 -DNAME=__reml -S -o $@ $< + +archclean: + rm -f arch/$(ARCH)/*.ss arch/$(ARCH)/*.lss + diff --git a/klibc/klibc/arch/alpha/README-gcc b/klibc/klibc/arch/alpha/README-gcc new file mode 100644 index 0000000000..9aaba72837 --- /dev/null +++ b/klibc/klibc/arch/alpha/README-gcc @@ -0,0 +1,23 @@ + The current Alpha chips don't provide hardware for integer + division. The C compiler expects the functions + + __divqu: 64-bit unsigned long divide + __remqu: 64-bit unsigned long remainder + __divq/__remq: signed 64-bit + __divlu/__remlu: unsigned 32-bit + __divl/__reml: signed 32-bit + + These are not normal C functions: instead of the normal calling + sequence, these expect their arguments in registers t10 and t11, and + return the result in t12 (aka pv). Register AT may be clobbered + (assembly temporary), anything else must be saved. + + Furthermore, the return address is in t9 instead of ra. + + Normal function Divide functions + --------------- ---------------- + v0 ($0) t12/pv ($27) + a0 ($16) t10 ($24) + a1 ($17) t11 ($25) + ra ($26) t9 ($23) + diff --git a/klibc/klibc/arch/alpha/crt0.S b/klibc/klibc/arch/alpha/crt0.S new file mode 100644 index 0000000000..6c2958117d --- /dev/null +++ b/klibc/klibc/arch/alpha/crt0.S @@ -0,0 +1,21 @@ +# +# arch/alpha/crt0.S +# + + .text + .type __start,@function + .ent __start, 0 + .globl __start +__start: + .frame $30, 0, $26, 0 + mov $31, $15 + br $29, 1f +1: ldgp $29, 0($29) + .prologue 0 + + lda $16, 0($30) # ELF data structure + lda $17, 0($0) # atexit pointer + + jsr $26, __libc_init + + .size __start,.-__start diff --git a/klibc/klibc/arch/alpha/divide.c b/klibc/klibc/arch/alpha/divide.c new file mode 100644 index 0000000000..49d77cd5dc --- /dev/null +++ b/klibc/klibc/arch/alpha/divide.c @@ -0,0 +1,57 @@ +#include <stdint.h> +#include <asm/gentrap.h> +#include <asm/pal.h> + +#if BITS == 64 +typedef uint64_t uint; +typedef int64_t sint; +#else +typedef uint32_t uint; +typedef int32_t sint; +#endif + +#ifdef SIGNED +typedef sint xint; +#else +typedef uint xint; +#endif + +xint NAME (uint num, uint den) +{ + uint quot = 0, qbit = 1; + int minus = 0; + xint v; + + if ( den == 0 ) { + /* This is really $16, but $16 and $24 are exchanged by a script */ + register unsigned long cause asm("$24") = GEN_INTDIV; + asm volatile("call_pal %0" :: "i" (PAL_gentrap), "r" (cause)); + return 0; /* If trap returns... */ + } + +#if SIGNED + if ( (sint)(num^den) < 0 ) + minus = 1; + if ( (sint)num < 0 ) num = -num; + if ( (sint)den < 0 ) den = -den; +#endif + + /* Left-justify denominator and count shift */ + while ( (sint)den >= 0 ) { + den <<= 1; + qbit <<= 1; + } + + while ( qbit ) { + if ( den <= num ) { + num -= den; + quot += qbit; + } + den >>= 1; + qbit >>= 1; + } + + v = (xint)(REM ? num : quot); + if ( minus ) v = -v; + return v; +} diff --git a/klibc/klibc/arch/alpha/include/klibc/archsetjmp.h b/klibc/klibc/arch/alpha/include/klibc/archsetjmp.h new file mode 100644 index 0000000000..9dc570a6f5 --- /dev/null +++ b/klibc/klibc/arch/alpha/include/klibc/archsetjmp.h @@ -0,0 +1,33 @@ +/* + * arch/alpha/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + unsigned long __s0; + unsigned long __s1; + unsigned long __s2; + unsigned long __s3; + unsigned long __s4; + unsigned long __s5; + unsigned long __fp; + unsigned long __ra; + unsigned long __gp; + unsigned long __sp; + + unsigned long __f2; + unsigned long __f3; + unsigned long __f4; + unsigned long __f5; + unsigned long __f6; + unsigned long __f7; + unsigned long __f8; + unsigned long __f9; +}; + +/* Must be an array so it will decay to a pointer when a function is called */ +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _KLIBC_ARCHSETJMP_H */ diff --git a/klibc/klibc/arch/alpha/include/klibc/archsys.h b/klibc/klibc/arch/alpha/include/klibc/archsys.h new file mode 100644 index 0000000000..16ed658987 --- /dev/null +++ b/klibc/klibc/arch/alpha/include/klibc/archsys.h @@ -0,0 +1,53 @@ +/* + * arch/alpha/include/klibc/archsys.h + * + * Architecture-specific syscall definitions + */ + +#ifndef _KLIBC_ARCHSYS_H +#define _KLIBC_ARCHSYS_H + +/* Alpha has some bizarre Tru64-derived system calls which return two + different values in $0 and $20(!), respectively. The standard + macros can't deal with these; even the ones that give the right + return value have the wrong clobbers. */ + +#define _syscall0_dual0(type, name) \ +type name(void) \ +{ \ + long _sc_ret, _sc_err; \ + { \ + register long _sc_0 __asm__("$0"); \ + register long _sc_19 __asm__("$19"); \ + register long _sc_20 __asm__("$20"); \ + \ + _sc_0 = __NR_##name; \ + __asm__("callsys" \ + : "=r"(_sc_0), "=r"(_sc_19), "=r" (_sc_20) \ + : "0"(_sc_0) \ + : _syscall_clobbers); \ + _sc_ret = _sc_0, _sc_err = _sc_19; (void)(_sc_20); \ + } \ + _syscall_return(type); \ +} + +#define _syscall0_dual1(type, name) \ +type name(void) \ +{ \ + long _sc_ret, _sc_err; \ + { \ + register long _sc_0 __asm__("$0"); \ + register long _sc_19 __asm__("$19"); \ + register long _sc_20 __asm__("$20"); \ + \ + _sc_0 = __NR_##name; \ + __asm__("callsys" \ + : "=r"(_sc_0), "=r"(_sc_19), "=r" (_sc_20) \ + : "0"(_sc_0) \ + : _syscall_clobbers); \ + _sc_ret = _sc_20, _sc_err = _sc_19; (void)(_sc_0); \ + } \ + _syscall_return(type); \ +} + +#endif /* _KLIBC_ARCHSYS_H */ diff --git a/klibc/klibc/arch/alpha/include/machine/asm.h b/klibc/klibc/arch/alpha/include/machine/asm.h new file mode 100644 index 0000000000..e22db90412 --- /dev/null +++ b/klibc/klibc/arch/alpha/include/machine/asm.h @@ -0,0 +1,44 @@ +/* + * machine/asm.h + */ + +#ifndef _MACHINE_ASM_H +#define _MACHINE_ASM_H + +/* Standard aliases for Alpha register names */ + +#define v0 $0 +#define t0 $1 +#define t1 $2 +#define t2 $3 +#define t3 $4 +#define t4 $5 +#define t5 $6 +#define t6 $7 +#define t7 $8 +#define s0 $9 +#define s1 $10 +#define s2 $11 +#define s3 $12 +#define s4 $13 +#define s5 $14 +#define fp $15 +#define a0 $16 +#define a1 $17 +#define a2 $18 +#define a3 $19 +#define a4 $20 +#define a5 $21 +#define t8 $22 +#define t9 $23 +#define t10 $24 +#define t11 $25 +#define ra $26 +#define t12 $27 /* t12 and pv are both used for $27 */ +#define pv $27 /* t12 and pv are both used for $27 */ +#define at $28 +#define gp $29 +#define sp $30 +#define zero $31 + +#endif /* _MACHINE_ASM_H */ diff --git a/klibc/klibc/arch/alpha/pipe.c b/klibc/klibc/arch/alpha/pipe.c new file mode 100644 index 0000000000..5aee9edbab --- /dev/null +++ b/klibc/klibc/arch/alpha/pipe.c @@ -0,0 +1,28 @@ +#include <unistd.h> +#include <sys/syscall.h> + +/* pipe() on alpha returns both file descriptors in registers -- + $0 and $20 respectively. This is unlike any other system call, + as far as I can tell. */ + +int pipe(int *fds) +{ + register long sc_0 __asm__("$0"); + register long sc_19 __asm__("$19"); + register long sc_20 __asm__("$20"); + + sc_0 = __NR_pipe; + asm volatile("callsys" : "=r" (sc_0), "=r" (sc_19), "=r" (sc_20) + : "0" (sc_0) + : _syscall_clobbers); + + if ( sc_19 ) { + errno = sc_19; + return -1; + } + + fds[0] = sc_0; + fds[1] = sc_20; + + return 0; +} diff --git a/klibc/klibc/arch/alpha/setjmp.S b/klibc/klibc/arch/alpha/setjmp.S new file mode 100644 index 0000000000..e1ad642539 --- /dev/null +++ b/klibc/klibc/arch/alpha/setjmp.S @@ -0,0 +1,77 @@ +# +# setjmp.S +# + +# +# The jmp_buf looks like: +# +# s0..5 +# fp +# ra +# gp +# sp +# + +#include <machine/asm.h> + + .text + .align 3 + .type setjmp,@function + .ent setjmp, 0 + .globl setjmp +setjmp: + lda v0, 0(zero) + stq s0, 0(a0) + stq s1, 8(a0) + stq s2, 16(a0) + stq s3, 24(a0) + stq s4, 32(a0) + stq s5, 40(a0) + stq fp, 48(a0) + stq ra, 56(a0) + stq gp, 64(a0) + stq sp, 72(a0) + stt f2, 80(a0) + stt f3, 88(a0) + stt f4, 96(a0) + stt f5, 104(a0) + stt f6, 112(a0) + stt f7, 120(a0) + stt f8, 128(a0) + stt f9, 136(a0) + ret zero,(ra),1 + + .size setjmp,.-setjmp + .end setjmp + + .type longjmp,@function + .ent longjmp, 0 + .globl longjmp +longjmp: + mov a1, v0 + ldq s0, 0(a0) + ldq s1, 8(a0) + ldq s2, 16(a0) + ldq s3, 24(a0) + ldq s4, 32(a0) + ldq s5, 40(a0) + ldq fp, 48(a0) + ldq ra, 56(a0) + ldq gp, 64(a0) + ldq sp, 72(a0) + ldt f2, 80(a0) + ldt f3, 88(a0) + ldt f4, 96(a0) + ldt f5, 104(a0) + ldt f6, 112(a0) + ldt f7, 120(a0) + ldt f8, 128(a0) + ldt f9, 136(a0) + /* We're bound to get a mispredict here, but at least give us + a chance to get the return stack back in sync... */ + ret zero,(ra),1 + + .size longjmp,.-longjmp + .end longjmp + + diff --git a/klibc/klibc/arch/arm/MCONFIG b/klibc/klibc/arch/arm/MCONFIG new file mode 100644 index 0000000000..6fbea32903 --- /dev/null +++ b/klibc/klibc/arch/arm/MCONFIG @@ -0,0 +1,26 @@ +# -*- makefile -*- +# +# arch/arm/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +THUMB = n +CPU_ARCH := armv4 +CPU_TUNE := strongarm + +OPTFLAGS = -Os -fomit-frame-pointer -march=$(CPU_ARCH) -mtune=$(CPU_TUNE) +BITSIZE = 32 + +ifeq ($(THUMB),y) +CPU_ARCH := $(CPU_ARCH)t +OPTFLAGS += -mthumb +LDFLAGS += --thumb-entry _start +endif + +# Extra linkflags when building the shared version of the library +# This address needs to be reachable using normal inter-module +# calls, and work on the memory models for this architecture +SHAREDFLAGS = -Ttext 0x01000200 diff --git a/klibc/klibc/arch/arm/Makefile.inc b/klibc/klibc/arch/arm/Makefile.inc new file mode 100644 index 0000000000..3ec8c051b2 --- /dev/null +++ b/klibc/klibc/arch/arm/Makefile.inc @@ -0,0 +1,31 @@ +# -*- makefile -*- +# +# arch/arm/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +ARCHOBJS = \ + libgcc/__divsi3.o \ + libgcc/__modsi3.o \ + libgcc/__udivsi3.o \ + libgcc/__umodsi3.o \ + libgcc/__udivmodsi4.o \ + libgcc/__divdi3.o \ + libgcc/__moddi3.o \ + libgcc/__udivdi3.o \ + libgcc/__umoddi3.o \ + libgcc/__udivmoddi4.o + +ifeq ($(THUMB),y) +ARCHOBJS += arch/arm/setjmp-thumb.o +LIBGCC = +else +ARCHOBJS += arch/arm/setjmp-arm.o +endif + +ARCHSOOBJS = $(patsubst %.o,%.lo,$(ARCHOBJS)) + +archclean: diff --git a/klibc/klibc/arch/arm/crt0.S b/klibc/klibc/arch/arm/crt0.S new file mode 100644 index 0000000000..8cd3640c30 --- /dev/null +++ b/klibc/klibc/arch/arm/crt0.S @@ -0,0 +1,25 @@ +# +# arch/arm/crt0.S +# +# void _start(void) +# { +# /* Divine up argc, argv, and envp */ +# environ = envp; +# exit(main(argc, argv, envp)); +# } +# + + .text + .align 4 + .type _start,#function + .globl _start + +#ifdef __thumb__ + .thumb_func +#endif + +_start: mov r0, sp + mov r1, #0 + bl __libc_init + + .size _start,.-_start diff --git a/klibc/klibc/arch/arm/include/klibc/archsetjmp.h b/klibc/klibc/arch/arm/include/klibc/archsetjmp.h new file mode 100644 index 0000000000..c956b50a90 --- /dev/null +++ b/klibc/klibc/arch/arm/include/klibc/archsetjmp.h @@ -0,0 +1,14 @@ +/* + * arch/i386/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + unsigned int regs[10]; +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _SETJMP_H */ diff --git a/klibc/klibc/arch/arm/include/klibc/archsys.h b/klibc/klibc/arch/arm/include/klibc/archsys.h new file mode 100644 index 0000000000..1a77e53a65 --- /dev/null +++ b/klibc/klibc/arch/arm/include/klibc/archsys.h @@ -0,0 +1,12 @@ +/* + * arch/arm/include/klibc/archsys.h + * + * Architecture-specific syscall definitions + */ + +#ifndef _KLIBC_ARCHSYS_H +#define _KLIBC_ARCHSYS_H + +/* No special syscall definitions for this architecture */ + +#endif /* _KLIBC_ARCHSYS_H */ diff --git a/klibc/klibc/arch/arm/setjmp-arm.S b/klibc/klibc/arch/arm/setjmp-arm.S new file mode 100644 index 0000000000..bcb30b4221 --- /dev/null +++ b/klibc/klibc/arch/arm/setjmp-arm.S @@ -0,0 +1,40 @@ +# +# arch/arm/setjmp.S +# +# setjmp/longjmp for the ARM architecture +# + +# +# The jmp_buf is assumed to contain the following, in order: +# r4 +# r5 +# r6 +# r7 +# r8 +# r9 +# r10 +# fp +# sp +# lr +# + + .text + .align 4 + .globl setjmp + .type setjmp, #function +setjmp: + stmia r0, {r4, r5, r6, r7, r8, r9, r10, fp, sp, lr} + mov r0, #0 + mov pc, lr + .size setjmp,.-setjmp + + .text + .align 4 + .globl longjmp + .type longjmp, #function +longjmp: + ldmia r0, {r4, r5, r6, r7, r8, r9, r10, fp, sp, lr} + movs r0, r1 + moveq r0, #1 + mov pc, lr + .size longjmp,.-longjmp diff --git a/klibc/klibc/arch/arm/setjmp-thumb.S b/klibc/klibc/arch/arm/setjmp-thumb.S new file mode 100644 index 0000000000..b581c5f7ad --- /dev/null +++ b/klibc/klibc/arch/arm/setjmp-thumb.S @@ -0,0 +1,58 @@ +# +# arch/arm/setjmp-thumb.S +# +# setjmp/longjmp for the ARM/thumb architecture +# + +# +# The jmp_buf is assumed to contain the following, in order: +# lr +# r4 +# r5 +# r6 +# r7 +# r8 +# r9 +# r10 +# fp +# sp +# + + .text + .align 4 + .globl setjmp + .type setjmp, #function + .thumb_func +setjmp: + mov r3, lr + stmia r0!, {r3, r4, r5, r6, r7} + mov r3, r8 + mov r4, r9 + mov r5, r10 + mov r6, fp + mov r7, sp + stmia r0!, {r3, r4, r5, r6, r7} + mov r0, #0 + mov pc, lr + .size setjmp,.-setjmp + + .text + .align 4 + .globl longjmp + .type longjmp, #function + .thumb_func +longjmp: + mov r2, r0 + add r0, #5*4 + ldmia r0!, {r3, r4, r5, r6, r7} + mov r8, r3 + mov r9, r4 + mov r10, r5 + mov fp, r6 + mov sp, r7 + ldmia r2!, {r3, r4, r5, r6, r7} + mov r0, r1 + bne 1f + mov r0, #1 +1: mov pc, r3 + .size longjmp,.-longjmp diff --git a/klibc/klibc/arch/cris/MCONFIG b/klibc/klibc/arch/cris/MCONFIG new file mode 100644 index 0000000000..27809ebbe7 --- /dev/null +++ b/klibc/klibc/arch/cris/MCONFIG @@ -0,0 +1,11 @@ +# -*- makefile -*- +# +# arch/cris/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +OPTFLAGS = -Os -fomit-frame-pointer +BITSIZE = 32 diff --git a/klibc/klibc/arch/cris/Makefile.inc b/klibc/klibc/arch/cris/Makefile.inc new file mode 100644 index 0000000000..41183fd64b --- /dev/null +++ b/klibc/klibc/arch/cris/Makefile.inc @@ -0,0 +1,10 @@ +# -*- makefile -*- +# +# arch/cris/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +archclean: diff --git a/klibc/klibc/arch/cris/include/klibc/archsys.h b/klibc/klibc/arch/cris/include/klibc/archsys.h new file mode 100644 index 0000000000..dfdc70a6de --- /dev/null +++ b/klibc/klibc/arch/cris/include/klibc/archsys.h @@ -0,0 +1,12 @@ +/* + * arch/cris/include/klibc/archsys.h + * + * Architecture-specific syscall definitions + */ + +#ifndef _KLIBC_ARCHSYS_H +#define _KLIBC_ARCHSYS_H + +/* No special syscall definitions for this architecture */ + +#endif /* _KLIBC_ARCHSYS_H */ diff --git a/klibc/klibc/arch/i386/MCONFIG b/klibc/klibc/arch/i386/MCONFIG new file mode 100644 index 0000000000..367ee89773 --- /dev/null +++ b/klibc/klibc/arch/i386/MCONFIG @@ -0,0 +1,32 @@ +# -*- makefile -*- +# +# arch/i386/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +# Comment this out to compile with register parameter passing +# This doesn't work right now because gcc 3.2 (at least) calls +# libgcc with the default calling convention instead of forcing +# them to be cdecl +# REGPARM = -mregparm=3 -DREGPARM + +gcc_major := $(shell $(CC) -v 2>&1 | awk '/gcc version/{print int($$3)}') + +OPTFLAGS = $(REGPARM) -march=i386 -Os + +ifeq ($(gcc_major),3) +OPTFLAGS += -falign-functions=0 -falign-jumps=0 -falign-loops=0 +else +OPTFLAGS += -malign-functions=0 -malign-jumps=0 -malign-loops=0 +endif + +BITSIZE = 32 + +# Extra linkflags when building the shared version of the library +# This address needs to be reachable using normal inter-module +# calls, and work on the memory models for this architecture +# 96 MB - normal binaries start at 128 MB +SHAREDFLAGS = -Ttext 0x06000200 diff --git a/klibc/klibc/arch/i386/Makefile.inc b/klibc/klibc/arch/i386/Makefile.inc new file mode 100644 index 0000000000..171248a796 --- /dev/null +++ b/klibc/klibc/arch/i386/Makefile.inc @@ -0,0 +1,27 @@ +# -*- makefile -*- +# +# arch/i386/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +ARCHOBJS = \ + arch/$(ARCH)/exits.o \ + arch/$(ARCH)/socketcall.o \ + arch/$(ARCH)/setjmp.o \ + arch/$(ARCH)/libgcc/__ashldi3.o \ + arch/$(ARCH)/libgcc/__ashrdi3.o \ + arch/$(ARCH)/libgcc/__lshrdi3.o \ + arch/$(ARCH)/libgcc/__muldi3.o \ + arch/$(ARCH)/libgcc/__negdi2.o \ + libgcc/__divdi3.o \ + libgcc/__moddi3.o \ + libgcc/__udivdi3.o \ + libgcc/__umoddi3.o \ + libgcc/__udivmoddi4.o + +ARCHSOOBJS = $(patsubst %.o,%.lo,$(ARCHOBJS)) + +archclean: diff --git a/klibc/klibc/arch/i386/crt0.S b/klibc/klibc/arch/i386/crt0.S new file mode 100644 index 0000000000..1c82eda513 --- /dev/null +++ b/klibc/klibc/arch/i386/crt0.S @@ -0,0 +1,33 @@ +# +# arch/i386/crt0.S +# +# Does arch-specific initialization and invokes __libc_init +# with the appropriate arguments. +# +# See __static_init.c or __shared_init.c for the expected +# arguments. +# + + .text + .align 4 + .type _start,@function + .globl _start +_start: + # Save the address of the ELF argument array + movl %esp,%eax # Address of ELF arguments + # Set up a faux stack frame for the benefit of gdb + xorl %ebp,%ebp + push %ebp # Keep gdb from getting confused + push %ebp # Keep gdb from getting confused + # Push the arguments and called __libc_init() +#ifndef REGPARM + push %edx # atexit() function + push %eax # ELF array +#endif + call __libc_init + # If __libc_init returns, problem... + ud2 + hlt + + .size _start, .-_start + diff --git a/klibc/klibc/arch/i386/exits.S b/klibc/klibc/arch/i386/exits.S new file mode 100644 index 0000000000..59ff563ad8 --- /dev/null +++ b/klibc/klibc/arch/i386/exits.S @@ -0,0 +1,45 @@ +# +# exit and _exit get included in *every* program, and gcc generates +# horrible code for them. Yes, this only saves a few bytes, but +# it does it in every program. +# + +#include <asm/unistd.h> + + .data + .align 4 + .globl __exit_handler + .type __exit_handler,@object +__exit_handler: + .long _exit + .size __exit_handler,4 + + .text + .align 4 + .globl exit + .type exit,@function +exit: + jmp *(__exit_handler) + .size exit,.-exit + + /* No need to save any registers... we're exiting! */ + .text + .align 4 + .globl _exit + .type _exit,@function +_exit: +#ifdef REGPARM + movl %eax,%ebx +#else + popl %ebx + popl %ebx +#endif +#if __NR_exit == 1 + xorl %eax,%eax + incl %eax +#else + movl $__NR_exit,%eax +#endif + int $0x80 + hlt + .size _exit,.-exit diff --git a/klibc/klibc/arch/i386/include/klibc/archsetjmp.h b/klibc/klibc/arch/i386/include/klibc/archsetjmp.h new file mode 100644 index 0000000000..db04314b8c --- /dev/null +++ b/klibc/klibc/arch/i386/include/klibc/archsetjmp.h @@ -0,0 +1,19 @@ +/* + * arch/i386/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + unsigned int __ebx; + unsigned int __esp; + unsigned int __ebp; + unsigned int __esi; + unsigned int __edi; + unsigned int __eip; +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _SETJMP_H */ diff --git a/klibc/klibc/arch/i386/include/klibc/archsys.h b/klibc/klibc/arch/i386/include/klibc/archsys.h new file mode 100644 index 0000000000..e21487b256 --- /dev/null +++ b/klibc/klibc/arch/i386/include/klibc/archsys.h @@ -0,0 +1,96 @@ +/* + * arch/i386/include/klibc/archsys.h + * + * Architecture-specific syscall definitions + */ + +#ifndef _KLIBC_ARCHSYS_H +#define _KLIBC_ARCHSYS_H + +/* + * If we're compiling i386 in PIC mode, we need to treat %ebx + * specially. Most of these are copied from the equivalent file in + * newlib and were written by Werner Almesberger. + */ +#if defined(__PIC__) + +/* _syscall0() is the same as non-PIC */ + +#undef _syscall1 +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) \ +{ \ +long __res; \ +__asm__ __volatile__ ("push %%ebx; movl %2,%%ebx; int $0x80; pop %%ebx" \ + : "=a" (__res) \ + : "0" (__NR_##name),"r" ((long)(arg1))); \ +__syscall_return(type,__res); \ +} + +#undef _syscall2 +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1,type2 arg2) \ +{ \ +long __res; \ +__asm__ __volatile__ ("push %%ebx; movl %2,%%ebx; int $0x80; pop %%ebx" \ + : "=a" (__res) \ + : "0" (__NR_##name),"r" ((long)(arg1)),"c" ((long)(arg2))); \ +__syscall_return(type,__res); \ +} + +#undef _syscall3 +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1,type2 arg2,type3 arg3) \ +{ \ +long __res; \ +__asm__ __volatile__ ("push %%ebx; movl %2,%%ebx; int $0x80; pop %%ebx" \ + : "=a" (__res) \ + : "0" (__NR_##name),"r" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3))); \ +__syscall_return(type,__res); \ +} + +#undef _syscall4 +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ +{ \ +long __res; \ +__asm__ __volatile__ ("push %%ebx; movl %2,%%ebx; int $0x80; pop %%ebx" \ + : "=a" (__res) \ + : "0" (__NR_##name),"r" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3)),"S" ((long)(arg4))); \ +__syscall_return(type,__res); \ +} + +#undef _syscall5 +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ +{ \ +long __res; \ +__asm__ __volatile__ ("push %%ebx; movl %2,%%ebx; int $0x80; pop %%ebx" \ + : "=a" (__res) \ + : "0" (__NR_##name),"m" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5))); \ +__syscall_return(type,__res); \ +} + +#undef _syscall6 +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5,type6,arg6) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \ +{ \ +long __res; \ +__asm__ __volatile__ ("push %%ebx; pushl %%ebp; movl %2,%%ebx; " \ + "movl %%eax,%%ebp; movl %1,%%eax; int $0x80; " \ + "pop %%ebp ; pop %%ebx" \ + : "=a" (__res) \ + : "i" (__NR_##name),"m" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)), \ + "a" ((long)(arg6))); \ +__syscall_return(type,__res); \ +} + +#endif /* __PIC__ */ + +#endif /* _KLIBC_ARCHSYS_H */ diff --git a/klibc/klibc/arch/i386/include/klibc/diverr.h b/klibc/klibc/arch/i386/include/klibc/diverr.h new file mode 100644 index 0000000000..410aba06d3 --- /dev/null +++ b/klibc/klibc/arch/i386/include/klibc/diverr.h @@ -0,0 +1,16 @@ +/* + * arch/i386/include/klibc/diverr.h + */ + +#ifndef _KLIBC_DIVERR_H +#define _KLIBC_DIVERR_H + +#include <signal.h> + +static __inline__ void +__divide_error(void) +{ + asm volatile("divl %0" :: "rm" (0) : "eax", "edx"); +} + +#endif /* _KLIBC_DIVERR_H */ diff --git a/klibc/klibc/arch/i386/libgcc/__ashldi3.S b/klibc/klibc/arch/i386/libgcc/__ashldi3.S new file mode 100644 index 0000000000..80ed4be3cf --- /dev/null +++ b/klibc/klibc/arch/i386/libgcc/__ashldi3.S @@ -0,0 +1,29 @@ +/* + * arch/i386/libgcc/__ashldi3.S + * + * 64-bit shl + */ + .text + .align 4 + .globl __ashldi3 + .type __ashldi3,@function +__ashldi3: +#ifndef REGPARM + movl 4(%esp),%eax + movl 8(%esp),%edx + movb 12(%esp),%cl +#endif + cmpb $32,%cl + jae 1f + + shldl %cl,%eax,%edx + shl %cl,%eax + ret + +1: + xorl %edx,%edx + shl %cl,%eax + xchgl %edx,%eax + ret + + .size __ashldi3,.-__ashldi3 diff --git a/klibc/klibc/arch/i386/libgcc/__ashrdi3.S b/klibc/klibc/arch/i386/libgcc/__ashrdi3.S new file mode 100644 index 0000000000..ba43f9022a --- /dev/null +++ b/klibc/klibc/arch/i386/libgcc/__ashrdi3.S @@ -0,0 +1,29 @@ +/* + * arch/i386/libgcc/__ashrdi3.S + * + * 64-bit sar + */ + .text + .align 4 + .globl __ashrdi3 + .type __ashrdi3,@function +__ashrdi3: +#ifndef REGPARM + movl 4(%esp),%eax + movl 8(%esp),%edx + movb 12(%esp),%cl +#endif + cmpb $32,%cl + jae 1f + + shrdl %cl,%edx,%eax + sarl %cl,%edx + ret + +1: + sarl %cl,%edx + movl %edx,%eax + cdq + ret + + .size __ashrdi3,.-__ashrdi3 diff --git a/klibc/klibc/arch/i386/libgcc/__lshrdi3.S b/klibc/klibc/arch/i386/libgcc/__lshrdi3.S new file mode 100644 index 0000000000..6e521ace2c --- /dev/null +++ b/klibc/klibc/arch/i386/libgcc/__lshrdi3.S @@ -0,0 +1,29 @@ +/* + * arch/i386/libgcc/__lshrdi3.S + * + * 64-bit shr + */ + .text + .align 4 + .globl __lshrdi3 + .type __lshrdi3,@function +__lshrdi3: +#ifndef REGPARM + movl 4(%esp),%eax + movl 8(%esp),%edx + movb 12(%esp),%cl +#endif + cmpb $32,%cl + jae 1f + + shrdl %cl,%edx,%eax + shrl %cl,%edx + ret + +1: + shrl %cl,%edx + xorl %eax,%eax + xchgl %edx,%eax + ret + + .size __lshrdi3,.-__lshrdi3 diff --git a/klibc/klibc/arch/i386/libgcc/__muldi3.S b/klibc/klibc/arch/i386/libgcc/__muldi3.S new file mode 100644 index 0000000000..c164588b16 --- /dev/null +++ b/klibc/klibc/arch/i386/libgcc/__muldi3.S @@ -0,0 +1,34 @@ +/* + * arch/i386/libgcc/__muldi3.S + * + * 64*64 = 64 bit unsigned multiplication + */ + + .text + .align 4 + .globl __muldi3 + .type __muldi3,@function +__muldi3: + push %esi +#ifndef REGPARM + movl 8(%esp),%eax + movl %eax,%esi + movl 16(%esp),%ecx + mull %ecx + imull 12(%esp),%ecx + imull 20(%esp),%esi + addl %ecx,%edx + addl %esi,%edx +#else + movl %eax,%esi + push %edx + mull %ecx + imull 8(%esp),%esi + addl %esi,%edx + pop %esi + imull %esi,%ecx + addl %ecx,%edx +#endif + pop %esi + ret + .size __muldi3,.-__muldi3 diff --git a/klibc/klibc/arch/i386/libgcc/__negdi2.S b/klibc/klibc/arch/i386/libgcc/__negdi2.S new file mode 100644 index 0000000000..6c95cb235c --- /dev/null +++ b/klibc/klibc/arch/i386/libgcc/__negdi2.S @@ -0,0 +1,21 @@ +/* + * arch/i386/libgcc/__negdi2.S + * + * 64-bit negation + */ + + .text + .align 4 + .globl __negdi2 + .type __negdi2,@function +__negdi2: +#ifndef REGPARM + movl 4(%esp),%eax + movl 8(%esp),%edx +#endif + negl %edx + negl %eax + sbbl $0,%edx + ret + + .size __negdi2,.-__negdi2 diff --git a/klibc/klibc/arch/i386/setjmp.S b/klibc/klibc/arch/i386/setjmp.S new file mode 100644 index 0000000000..bea900c519 --- /dev/null +++ b/klibc/klibc/arch/i386/setjmp.S @@ -0,0 +1,58 @@ +# +# arch/i386/setjmp.S +# +# setjmp/longjmp for the i386 architecture +# + +# +# The jmp_buf is assumed to contain the following, in order: +# %ebx +# %esp +# %ebp +# %esi +# %edi +# <return address> +# + + .text + .align 4 + .globl setjmp + .type setjmp, @function +setjmp: +#ifdef REGPARM + movl %eax,%edx +#else + movl 4(%esp),%edx +#endif + popl %ecx # Return address, and adjust the stack + xorl %eax,%eax # Return value + movl %ebx,(%edx) + movl %esp,4(%edx) # Post-return %esp! + pushl %ecx # Make the call/return stack happy + movl %ebp,8(%edx) + movl %esi,12(%edx) + movl %edi,16(%edx) + movl %ecx,20(%edx) # Return address + ret + + .size setjmp,.-setjmp + + .text + .align 4 + .globl longjmp + .type longjmp, @function +longjmp: +#ifdef REGPARM + xchgl %eax,%edx +#else + movl 4(%esp),%edx # jmp_ptr address + movl 8(%esp),%eax # Return value +#endif + movl (%edx),%ebx + movl 4(%edx),%esp + movl 8(%edx),%ebp + movl 12(%edx),%esi + movl 16(%edx),%edi + jmp *20(%edx) + + .size longjmp,.-longjmp diff --git a/klibc/klibc/arch/i386/socketcall.S b/klibc/klibc/arch/i386/socketcall.S new file mode 100644 index 0000000000..6bac1e6913 --- /dev/null +++ b/klibc/klibc/arch/i386/socketcall.S @@ -0,0 +1,38 @@ +# +# socketcall.S +# +# On i386, the main (only?) user of socketcall(2), the memory array +# socketcall(2) needs is conveniently already assembled for us on +# the stack. Capitalize on that to make a common socketcall stub. +# + +#include <asm/unistd.h> + +#ifdef __i386__ + + .text + .align 4 + .globl __socketcall_common + .type __socketcall_common, @function + +__socketcall_common: + pushl %ebx + movzbl %al,%ebx # The socketcall number is passed in in %al + leal 8(%esp),%ecx # Argument pointer + movl $__NR_socketcall, %eax + int $0x80 + cmpl $-125,%eax # Error return? + popl %ebx + jb 1f + neg %eax + movl %eax,errno + xorl %eax,%eax + decl %eax # Return = -1 +1: + ret + + .size __socketcall_common,.-__socketcall_common + +#endif + + diff --git a/klibc/klibc/arch/ia64/MCONFIG b/klibc/klibc/arch/ia64/MCONFIG new file mode 100644 index 0000000000..631a478e4f --- /dev/null +++ b/klibc/klibc/arch/ia64/MCONFIG @@ -0,0 +1,11 @@ +# -*- makefile -*- +# +# arch/ia64/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +OPTFLAGS = -Os -fomit-frame-pointer +BITSIZE = 64 diff --git a/klibc/klibc/arch/ia64/Makefile.inc b/klibc/klibc/arch/ia64/Makefile.inc new file mode 100644 index 0000000000..1fb364f92e --- /dev/null +++ b/klibc/klibc/arch/ia64/Makefile.inc @@ -0,0 +1,10 @@ +# -*- makefile -*- +# +# arch/ia64/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +archclean: diff --git a/klibc/klibc/arch/ia64/include/klibc/archsys.h b/klibc/klibc/arch/ia64/include/klibc/archsys.h new file mode 100644 index 0000000000..ef5940ac25 --- /dev/null +++ b/klibc/klibc/arch/ia64/include/klibc/archsys.h @@ -0,0 +1,12 @@ +/* + * arch/ia64/include/klibc/archsys.h + * + * Architecture-specific syscall definitions + */ + +#ifndef _KLIBC_ARCHSYS_H +#define _KLIBC_ARCHSYS_H + +/* No special syscall definitions for this architecture */ + +#endif /* _KLIBC_ARCHSYS_H */ diff --git a/klibc/klibc/arch/m68k/MCONFIG b/klibc/klibc/arch/m68k/MCONFIG new file mode 100644 index 0000000000..2ba69b3178 --- /dev/null +++ b/klibc/klibc/arch/m68k/MCONFIG @@ -0,0 +1,11 @@ +# -*- makefile -*- +# +# arch/m68k/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +OPTFLAGS = -Os -fomit-frame-pointer +BITSIZE = 32 diff --git a/klibc/klibc/arch/m68k/Makefile.inc b/klibc/klibc/arch/m68k/Makefile.inc new file mode 100644 index 0000000000..9abec14db1 --- /dev/null +++ b/klibc/klibc/arch/m68k/Makefile.inc @@ -0,0 +1,10 @@ +# -*- makefile -*- +# +# arch/m68k/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +archclean: diff --git a/klibc/klibc/arch/m68k/include/klibc/archsys.h b/klibc/klibc/arch/m68k/include/klibc/archsys.h new file mode 100644 index 0000000000..8f6bed8e94 --- /dev/null +++ b/klibc/klibc/arch/m68k/include/klibc/archsys.h @@ -0,0 +1,12 @@ +/* + * arch/m68k/include/klibc/archsys.h + * + * Architecture-specific syscall definitions + */ + +#ifndef _KLIBC_ARCHSYS_H +#define _KLIBC_ARCHSYS_H + +/* No special syscall definitions for this architecture */ + +#endif /* _KLIBC_ARCHSYS_H */ diff --git a/klibc/klibc/arch/mips/MCONFIG b/klibc/klibc/arch/mips/MCONFIG new file mode 100644 index 0000000000..52b518461f --- /dev/null +++ b/klibc/klibc/arch/mips/MCONFIG @@ -0,0 +1,18 @@ +# -*- makefile -*- +# +# arch/mips/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +ARCHREQFLAGS = -fno-pic -mno-abicalls +OPTFLAGS = -Os -fomit-frame-pointer +BITSIZE = 32 + +# Extra linkflags when building the shared version of the library +# This address needs to be reachable using normal inter-module +# calls, and work on the memory models for this architecture +# 2 MB -- the normal starting point for text is 4 MB. +SHAREDFLAGS = -Ttext 0x00200200 diff --git a/klibc/klibc/arch/mips/Makefile.inc b/klibc/klibc/arch/mips/Makefile.inc new file mode 100644 index 0000000000..09a2d2f736 --- /dev/null +++ b/klibc/klibc/arch/mips/Makefile.inc @@ -0,0 +1,24 @@ +# -*- makefile -*- +# +# arch/mips/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +ARCHOBJS = \ + arch/$(ARCH)/pipe.o \ + arch/$(ARCH)/vfork.o \ + arch/$(ARCH)/setjmp.o \ + libgcc/__divdi3.o \ + libgcc/__moddi3.o \ + libgcc/__udivdi3.o \ + libgcc/__umoddi3.o \ + libgcc/__udivmoddi4.o + + +ARCHSOOBJS = $(patsubst %.o,%.lo,$(ARCHOBJS)) + + +archclean: diff --git a/klibc/klibc/arch/mips/crt0.S b/klibc/klibc/arch/mips/crt0.S new file mode 100644 index 0000000000..42d9dd5e38 --- /dev/null +++ b/klibc/klibc/arch/mips/crt0.S @@ -0,0 +1,25 @@ +# +# arch/mips/crt0.S +# +# Does arch-specific initialization and invokes __libc_init +# with the appropriate arguments. +# +# See __static_init.c or __shared_init.c for the expected +# arguments. +# + +#include <machine/asm.h> + +NESTED(__start, 32, sp) + subu sp, 32 + sw zero, 16(sp) + + lui gp, %hi(_gp) # Initialize gp + addiu gp, gp, _gp + + addiu a0, sp, 32 # Pointer to ELF entry structure + move a1, v0 # Kernel-provided atexit() pointer + + jal __libc_init + + END(__start) diff --git a/klibc/klibc/arch/mips/include/klibc/archsetjmp.h b/klibc/klibc/arch/mips/include/klibc/archsetjmp.h new file mode 100644 index 0000000000..40e5be2736 --- /dev/null +++ b/klibc/klibc/arch/mips/include/klibc/archsetjmp.h @@ -0,0 +1,39 @@ +/* + * arch/mips/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + unsigned long __s0; + unsigned long __s1; + unsigned long __s2; + unsigned long __s3; + unsigned long __s4; + unsigned long __s5; + unsigned long __s6; + unsigned long __s7; + unsigned long __gp; + unsigned long __sp; + unsigned long __s8; + unsigned long __ra; + unsigned long __f20; + unsigned long __f21; + unsigned long __f22; + unsigned long __f23; + unsigned long __f24; + unsigned long __f25; + unsigned long __f26; + unsigned long __f27; + unsigned long __f28; + unsigned long __f29; + unsigned long __f30; + unsigned long __f31; + unsigned long __fcr31; + unsigned long __unused; +} __attribute__((aligned(8))); + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _KLIBC_ARCHSETJMP_H */ diff --git a/klibc/klibc/arch/mips/include/klibc/archsys.h b/klibc/klibc/arch/mips/include/klibc/archsys.h new file mode 100644 index 0000000000..f696cdfaa7 --- /dev/null +++ b/klibc/klibc/arch/mips/include/klibc/archsys.h @@ -0,0 +1,12 @@ +/* + * arch/mips/include/klibc/archsys.h + * + * Architecture-specific syscall definitions + */ + +#ifndef _KLIBC_ARCHSYS_H +#define _KLIBC_ARCHSYS_H + +/* No special syscall definitions for this architecture */ + +#endif /* _KLIBC_ARCHSYS_H */ diff --git a/klibc/klibc/arch/mips/include/machine/asm.h b/klibc/klibc/arch/mips/include/machine/asm.h new file mode 100644 index 0000000000..e5239a6cef --- /dev/null +++ b/klibc/klibc/arch/mips/include/machine/asm.h @@ -0,0 +1,11 @@ +/* + * arch/mips/include/machine/asm.h + */ + +#ifndef _MACHINE_ASM_H +#define _MACHINE_ASM_H + +#include <asm/regdef.h> +#include <asm/asm.h> + +#endif /* _MACHINE_ASM_H */ diff --git a/klibc/klibc/arch/mips/include/sgidefs.h b/klibc/klibc/arch/mips/include/sgidefs.h new file mode 100644 index 0000000000..eb103ace2c --- /dev/null +++ b/klibc/klibc/arch/mips/include/sgidefs.h @@ -0,0 +1,20 @@ +/* + * arch/mips/include/sgidefs.h + */ + +/* Some ABI constants */ + +#ifndef _SGIDEFS_H +#define _SGIDEFS_H + +#define _MIPS_ISA_MIPS1 1 +#define _MIPS_ISA_MIPS2 2 +#define _MIPS_ISA_MIPS3 3 +#define _MIPS_ISA_MIPS4 4 +#define _MIPS_ISA_MIPS5 5 + +#define _MIPS_SIM_ABI32 1 +#define _MIPS_SIM_NABI32 2 +#define _MIPS_SIM_ABI64 3 + +#endif /* _SGIDEFS_H */ diff --git a/klibc/klibc/arch/mips/pipe.S b/klibc/klibc/arch/mips/pipe.S new file mode 100644 index 0000000000..d79f614025 --- /dev/null +++ b/klibc/klibc/arch/mips/pipe.S @@ -0,0 +1,16 @@ +#include <asm/asm.h> +#include <asm/regdef.h> +#include <asm/unistd.h> + +LEAF(pipe) + li v0, __NR_pipe + syscall + bnez a3, 1f + sw v0, (a0) + sw v1, (a1) + li v0, 0 + b 2f +1: sw v0, errno + li v0, -1 +2: jr ra + END(pipe) diff --git a/klibc/klibc/arch/mips/setjmp.S b/klibc/klibc/arch/mips/setjmp.S new file mode 100644 index 0000000000..4d293757ec --- /dev/null +++ b/klibc/klibc/arch/mips/setjmp.S @@ -0,0 +1,82 @@ +# +# arch/mips/setjmp.S +# +# setjmp/longjmp for the MIPS architecture +# +# The jmp_buf is assumed to contain the following, in order: +# s0..s7 +# gp +# sp +# s8 +# ra +# f20..f31 +# fcr31 +# + +#include <machine/asm.h> + +LEAF(setjmp) + sw s0, 0(a0) + sw s1, 4(a0) + sw s2, 8(a0) + sw s3, 12(a0) + sw s4, 16(a0) + sw s5, 20(a0) + sw s6, 24(a0) + sw s7, 28(a0) + sw gp, 32(a0) + sw sp, 36(a0) + sw s8, 40(a0) + sw ra, 44(a0) + cfc1 t0,$31 + swc1 $f20,48(a0) + swc1 $f21,52(a0) + swc1 $f22,56(a0) + swc1 $f23,60(a0) + swc1 $f24,64(a0) + swc1 $f25,68(a0) + swc1 $f26,72(a0) + swc1 $f27,76(a0) + swc1 $f28,80(a0) + swc1 $f29,84(a0) + swc1 $f30,88(a0) + swc1 $f31,92(a0) + sw t0,96(a0) + move v0,zero + jr ra + + END(setjmp) + +LEAF(longjmp) + lw s0, 0(a0) + lw s1, 4(a0) + lw s2, 8(a0) + lw s3, 12(a0) + lw s4, 16(a0) + lw s5, 20(a0) + lw s6, 24(a0) + lw s7, 28(a0) + lw gp, 32(a0) + lw sp, 36(a0) + lw s8, 40(a0) + lw ra, 44(a0) + lw t0, 96(a0) + lwc1 $f20,48(a0) + lwc1 $f21,52(a0) + lwc1 $f22,56(a0) + lwc1 $f23,60(a0) + lwc1 $f24,64(a0) + lwc1 $f25,68(a0) + lwc1 $f26,72(a0) + lwc1 $f27,76(a0) + lwc1 $f28,80(a0) + lwc1 $f29,84(a0) + lwc1 $f30,88(a0) + lwc1 $f31,92(a0) + ctc1 t0,$31 + move v0,a1 + jr ra + + END(longjmp) + +
\ No newline at end of file diff --git a/klibc/klibc/arch/mips/vfork.S b/klibc/klibc/arch/mips/vfork.S new file mode 100644 index 0000000000..aca8083aa4 --- /dev/null +++ b/klibc/klibc/arch/mips/vfork.S @@ -0,0 +1,19 @@ +#include <asm/asm.h> +#include <asm/regdef.h> +#include <asm/unistd.h> + +#define CLONE_VM 0x00000100 +#define CLONE_VFORK 0x00004000 +#define SIGCHLD 18 + +LEAF(vfork) + li a0, CLONE_VFORK | CLONE_VM | SIGCHLD + li a1, 0 + li v0, __NR_clone + syscall + bnez a3, 1f + b 2f +1: sw v0, errno + li v0, -1 +2: jr ra + END(vfork) diff --git a/klibc/klibc/arch/mips64/MCONFIG b/klibc/klibc/arch/mips64/MCONFIG new file mode 100644 index 0000000000..6a817e54b6 --- /dev/null +++ b/klibc/klibc/arch/mips64/MCONFIG @@ -0,0 +1,11 @@ +# -*- makefile -*- +# +# arch/mips64/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +OPTFLAGS = -Os -fomit-frame-pointer +BITSIZE = 64 diff --git a/klibc/klibc/arch/mips64/Makefile.inc b/klibc/klibc/arch/mips64/Makefile.inc new file mode 100644 index 0000000000..4a9529adca --- /dev/null +++ b/klibc/klibc/arch/mips64/Makefile.inc @@ -0,0 +1,10 @@ +# -*- makefile -*- +# +# arch/mips64/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +archclean: diff --git a/klibc/klibc/arch/mips64/include/klibc/archsys.h b/klibc/klibc/arch/mips64/include/klibc/archsys.h new file mode 100644 index 0000000000..81e5106e16 --- /dev/null +++ b/klibc/klibc/arch/mips64/include/klibc/archsys.h @@ -0,0 +1,12 @@ +/* + * arch/mips64/include/klibc/archsys.h + * + * Architecture-specific syscall definitions + */ + +#ifndef _KLIBC_ARCHSYS_H +#define _KLIBC_ARCHSYS_H + +/* No special syscall definitions for this architecture */ + +#endif /* _KLIBC_ARCHSYS_H */ diff --git a/klibc/klibc/arch/parisc/MCONFIG b/klibc/klibc/arch/parisc/MCONFIG new file mode 100644 index 0000000000..93a31707c6 --- /dev/null +++ b/klibc/klibc/arch/parisc/MCONFIG @@ -0,0 +1,11 @@ +# -*- makefile -*- +# +# arch/parisc/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +OPTFLAGS = -Os -fomit-frame-pointer +BITSIZE = 32 diff --git a/klibc/klibc/arch/parisc/Makefile.inc b/klibc/klibc/arch/parisc/Makefile.inc new file mode 100644 index 0000000000..f7a983da7f --- /dev/null +++ b/klibc/klibc/arch/parisc/Makefile.inc @@ -0,0 +1,10 @@ +# -*- makefile -*- +# +# arch/parisc/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +archclean: diff --git a/klibc/klibc/arch/parisc/include/klibc/archsys.h b/klibc/klibc/arch/parisc/include/klibc/archsys.h new file mode 100644 index 0000000000..5013ba8794 --- /dev/null +++ b/klibc/klibc/arch/parisc/include/klibc/archsys.h @@ -0,0 +1,12 @@ +/* + * arch/parisc/include/klibc/archsys.h + * + * Architecture-specific syscall definitions + */ + +#ifndef _KLIBC_ARCHSYS_H +#define _KLIBC_ARCHSYS_H + +/* No special syscall definitions for this architecture */ + +#endif /* _KLIBC_ARCHSYS_H */ diff --git a/klibc/klibc/arch/ppc/MCONFIG b/klibc/klibc/arch/ppc/MCONFIG new file mode 100644 index 0000000000..fcb0992150 --- /dev/null +++ b/klibc/klibc/arch/ppc/MCONFIG @@ -0,0 +1,11 @@ +# -*- makefile -*- +# +# arch/ppc/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +OPTFLAGS = -Os -fomit-frame-pointer +BITSIZE = 32 diff --git a/klibc/klibc/arch/ppc/Makefile.inc b/klibc/klibc/arch/ppc/Makefile.inc new file mode 100644 index 0000000000..6e87a48d6b --- /dev/null +++ b/klibc/klibc/arch/ppc/Makefile.inc @@ -0,0 +1,15 @@ +# -*- makefile -*- +# +# arch/ppc/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +ARCHOBJS = \ + arch/$(ARCH)/setjmp.o + +ARCHSOOBJS = $(patsubst %.o,%.lo,$(ARCHOBJS)) + +archclean: diff --git a/klibc/klibc/arch/ppc/crt0.S b/klibc/klibc/arch/ppc/crt0.S new file mode 100644 index 0000000000..f7274b07dd --- /dev/null +++ b/klibc/klibc/arch/ppc/crt0.S @@ -0,0 +1,29 @@ +# +# arch/ppc/crt0.S +# +# void _start(void) +# { +# /* Divine up argc, argv, and envp */ +# environ = envp; +# exit(main(argc, argv, envp)); +# } +# + + .text + .align 4 + .type _start,@function + .globl _start +_start: + lwz 3,0(1) + addi 4,1,4 + addi 5,1,8 + slwi 0,3,2 + add 5,5,0 + li 0,0 + stwu 0,-16(1) + lis 9,environ@ha + stw 5,environ@l(9) + bl main + bl exit + + .size _start,.-_start diff --git a/klibc/klibc/arch/ppc/include/klibc/archsetjmp.h b/klibc/klibc/arch/ppc/include/klibc/archsetjmp.h new file mode 100644 index 0000000000..53e2fccc3b --- /dev/null +++ b/klibc/klibc/arch/ppc/include/klibc/archsetjmp.h @@ -0,0 +1,36 @@ +/* + * arch/ppc/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + unsigned long __r2; + unsigned long __sp; + unsigned long __lr; + unsigned long __cr; + unsigned long __r13; + unsigned long __r14; + unsigned long __r15; + unsigned long __r16; + unsigned long __r17; + unsigned long __r18; + unsigned long __r19; + unsigned long __r20; + unsigned long __r21; + unsigned long __r22; + unsigned long __r23; + unsigned long __r24; + unsigned long __r25; + unsigned long __r26; + unsigned long __r27; + unsigned long __r28; + unsigned long __r29; + unsigned long __r30; + unsigned long __r31; +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _SETJMP_H */ diff --git a/klibc/klibc/arch/ppc/include/klibc/archsys.h b/klibc/klibc/arch/ppc/include/klibc/archsys.h new file mode 100644 index 0000000000..33a5ff3236 --- /dev/null +++ b/klibc/klibc/arch/ppc/include/klibc/archsys.h @@ -0,0 +1,55 @@ +/* + * arch/ppc/include/klibc/archsys.h + * + * Architecture-specific syscall definitions + */ + +#ifndef _KLIBC_ARCHSYS_H +#define _KLIBC_ARCHSYS_H + +/* PowerPC seems to lack _syscall6() in its headers */ +/* This seems to work on both 32- and 64-bit ppc */ + +#ifndef _syscall6 + +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5,type6,arg6) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \ +{ \ + unsigned long __sc_ret, __sc_err; \ + { \ + register unsigned long __sc_0 __asm__ ("r0"); \ + register unsigned long __sc_3 __asm__ ("r3"); \ + register unsigned long __sc_4 __asm__ ("r4"); \ + register unsigned long __sc_5 __asm__ ("r5"); \ + register unsigned long __sc_6 __asm__ ("r6"); \ + register unsigned long __sc_7 __asm__ ("r7"); \ + register unsigned long __sc_8 __asm__ ("r8"); \ + \ + __sc_3 = (unsigned long) (arg1); \ + __sc_4 = (unsigned long) (arg2); \ + __sc_5 = (unsigned long) (arg3); \ + __sc_6 = (unsigned long) (arg4); \ + __sc_7 = (unsigned long) (arg5); \ + __sc_8 = (unsigned long) (arg6); \ + __sc_0 = __NR_##name; \ + __asm__ __volatile__ \ + ("sc \n\t" \ + "mfcr %1 " \ + : "=&r" (__sc_3), "=&r" (__sc_0) \ + : "0" (__sc_3), "1" (__sc_0), \ + "r" (__sc_4), \ + "r" (__sc_5), \ + "r" (__sc_6), \ + "r" (__sc_7), \ + "r" (__sc_8) \ + : __syscall_clobbers); \ + __sc_ret = __sc_3; \ + __sc_err = __sc_0; \ + } \ + __syscall_return (type); \ +} + +#endif /* _syscall6() missing */ + +#endif /* _KLIBC_ARCHSYS_H */ diff --git a/klibc/klibc/arch/ppc/setjmp.S b/klibc/klibc/arch/ppc/setjmp.S new file mode 100644 index 0000000000..1c50301707 --- /dev/null +++ b/klibc/klibc/arch/ppc/setjmp.S @@ -0,0 +1,35 @@ +# +# arch/ppc/setjmp.S +# +# Basic setjmp/longjmp implementation +# This file was derived from the equivalent file in NetBSD +# + + .text + .align 4 + .type setjmp,@function + .globl setjmp +setjmp: + mflr %r11 /* save return address */ + mfcr %r12 /* save condition register */ + mr %r10,%r1 /* save stack pointer */ + mr %r9,%r2 /* save GPR2 (not needed) */ + stmw %r9,0(%r3) /* save r9..r31 */ + li %r3,0 /* indicate success */ + blr /* return */ + + .size setjmp,.-setjmp + + .type longjmp,@function + .globl longjmp +longjmp: + lmw %r9,0(%r3) /* save r9..r31 */ + mtlr %r11 /* restore LR */ + mtcr %r12 /* restore CR */ + mr %r2,%r9 /* restore GPR2 (not needed) */ + mr %r1,%r10 /* restore stack */ + mr %r3,%r4 /* get return value */ + blr /* return */ + + .size longjmp,.-longjmp +
\ No newline at end of file diff --git a/klibc/klibc/arch/ppc64/MCONFIG b/klibc/klibc/arch/ppc64/MCONFIG new file mode 100644 index 0000000000..6997693e99 --- /dev/null +++ b/klibc/klibc/arch/ppc64/MCONFIG @@ -0,0 +1,11 @@ +# -*- makefile -*- +# +# arch/ppc64/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +OPTFLAGS = -Os -fomit-frame-pointer +BITSIZE = 64 diff --git a/klibc/klibc/arch/ppc64/Makefile.inc b/klibc/klibc/arch/ppc64/Makefile.inc new file mode 100644 index 0000000000..434d0aad96 --- /dev/null +++ b/klibc/klibc/arch/ppc64/Makefile.inc @@ -0,0 +1,10 @@ +# -*- makefile -*- +# +# arch/ppc64/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +archclean: diff --git a/klibc/klibc/arch/ppc64/crt0.S b/klibc/klibc/arch/ppc64/crt0.S new file mode 100644 index 0000000000..2f352e8045 --- /dev/null +++ b/klibc/klibc/arch/ppc64/crt0.S @@ -0,0 +1,38 @@ +# +# arch/ppc64/crt0.S +# +# void _start(void) +# { +# /* Divine up argc, argv, and envp */ +# environ = envp; +# exit(main(argc, argv, envp)); +# } +# + + .section ".toc","aw" +.LC0: .tc environ[TC],environ + + .section ".opd","aw" + .align 3 + .globl _start +_start: + .quad ._start + .quad .TOC.@tocbase, 0 + + .text + .globl ._start + .type ._start,@function +._start: + ld 3,0(1) + ld 4,8(1) + ld 5,16(1) + li 0,0 + stdu 0,-64(1) + ld 9,.LC0@toc(2) + std 5,0(9) + bl .main + nop + bl .exit + nop + + .size _start,.-_start diff --git a/klibc/klibc/arch/ppc64/include/klibc/archsys.h b/klibc/klibc/arch/ppc64/include/klibc/archsys.h new file mode 100644 index 0000000000..4f81fee00d --- /dev/null +++ b/klibc/klibc/arch/ppc64/include/klibc/archsys.h @@ -0,0 +1,52 @@ +/* + * arch/ppc64/include/klibc/archsys.h + * + * Architecture-specific syscall definitions + */ + +#ifndef _KLIBC_ARCHSYS_H +#define _KLIBC_ARCHSYS_H + +#ifndef _syscall6 + +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5,type6,arg6) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \ +{ \ + unsigned long __sc_ret, __sc_err; \ + { \ + register unsigned long __sc_0 __asm__ ("r0"); \ + register unsigned long __sc_3 __asm__ ("r3"); \ + register unsigned long __sc_4 __asm__ ("r4"); \ + register unsigned long __sc_5 __asm__ ("r5"); \ + register unsigned long __sc_6 __asm__ ("r6"); \ + register unsigned long __sc_7 __asm__ ("r7"); \ + register unsigned long __sc_8 __asm__ ("r8"); \ + \ + __sc_3 = (unsigned long) (arg1); \ + __sc_4 = (unsigned long) (arg2); \ + __sc_5 = (unsigned long) (arg3); \ + __sc_6 = (unsigned long) (arg4); \ + __sc_7 = (unsigned long) (arg5); \ + __sc_8 = (unsigned long) (arg6); \ + __sc_0 = __NR_##name; \ + __asm__ __volatile__ \ + ("sc \n\t" \ + "mfcr %1 " \ + : "=&r" (__sc_3), "=&r" (__sc_0) \ + : "0" (__sc_3), "1" (__sc_0), \ + "r" (__sc_4), \ + "r" (__sc_5), \ + "r" (__sc_6), \ + "r" (__sc_7), \ + "r" (__sc_8) \ + : __syscall_clobbers); \ + __sc_ret = __sc_3; \ + __sc_err = __sc_0; \ + } \ + __syscall_return (type); \ +} + +#endif /* _syscall6() missing */ + +#endif /* _KLIBC_ARCHSYS_H */ diff --git a/klibc/klibc/arch/s390/MCONFIG b/klibc/klibc/arch/s390/MCONFIG new file mode 100644 index 0000000000..e32c33faa1 --- /dev/null +++ b/klibc/klibc/arch/s390/MCONFIG @@ -0,0 +1,13 @@ +# -*- makefile -*- +# +# arch/s390/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +OPTFLAGS = -Os -fomit-frame-pointer +BITSIZE = 32 + +SHAREDFLAGS = -Ttext 0x40000200 diff --git a/klibc/klibc/arch/s390/Makefile.inc b/klibc/klibc/arch/s390/Makefile.inc new file mode 100644 index 0000000000..45aa551695 --- /dev/null +++ b/klibc/klibc/arch/s390/Makefile.inc @@ -0,0 +1,16 @@ +# -*- makefile -*- +# +# arch/s390/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +ARCHOBJS = \ + arch/$(ARCH)/setjmp.o + +ARCHSOOBJS = $(patsubst %.o,%.lo,$(ARCHOBJS)) + + +archclean: diff --git a/klibc/klibc/arch/s390/crt0.S b/klibc/klibc/arch/s390/crt0.S new file mode 100644 index 0000000000..49c3e7ebc7 --- /dev/null +++ b/klibc/klibc/arch/s390/crt0.S @@ -0,0 +1,25 @@ +# +# arch/s390/crt0.S +# +# Does arch-specific initialization and invokes __libc_init +# with the appropriate arguments. +# +# See __static_init.c or __shared_init.c for the expected +# arguments. +# + .text + .align 4 + .type _start,@function + .globl _start +_start: + lr %r2,%r15 + lhi %r3,0 + ahi %r15,-96 + bras %r1,.L0 +.L0: + l %r1,.L1-.L0(%r1) + br %r1 +.L1: + .long __libc_init + + .size _start,.-_start diff --git a/klibc/klibc/arch/s390/include/klibc/archsetjmp.h b/klibc/klibc/arch/s390/include/klibc/archsetjmp.h new file mode 100644 index 0000000000..11a641ed5a --- /dev/null +++ b/klibc/klibc/arch/s390/include/klibc/archsetjmp.h @@ -0,0 +1,15 @@ +/* + * arch/s390/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + uint32_t __gregs[10]; /* general registers r6-r15 */ + uint64_t __fpregs[2]; /* fp registers f4 and f6 */ +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _SETJMP_H */ diff --git a/klibc/klibc/arch/s390/include/klibc/archsys.h b/klibc/klibc/arch/s390/include/klibc/archsys.h new file mode 100644 index 0000000000..1cd0948f3c --- /dev/null +++ b/klibc/klibc/arch/s390/include/klibc/archsys.h @@ -0,0 +1,41 @@ +/* + * arch/s390/include/klibc/archsys.h + * + * Architecture-specific syscall definitions + */ + +#ifndef _KLIBC_ARCHSYS_H +#define _KLIBC_ARCHSYS_H + +/* S/390 only has five syscall parameters, and uses a structure for + 6-argument syscalls. */ + +#ifndef _syscall6 + +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,\ + type4,arg4,type5,arg5,type6,arg6) \ +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ + type5 arg5, type6 arg6) { \ + unsigned long __arg[6] = { \ + (unsigned long) arg1, \ + (unsigned long) arg2, \ + (unsigned long) arg3, \ + (unsigned long) arg4, \ + (unsigned long) arg5, \ + (unsigned long) arg6 \ + }; \ + register void *__argp asm("2") = &__arg; \ + long __res; \ + __asm__ __volatile__ ( \ + " svc %b1\n" \ + " lr %0,2" \ + : "=d" (__res) \ + : "i" (__NR_##name), \ + "d" (__argp) \ + : _svc_clobber); \ + __syscall_return(type, __res); \ +} + +#endif /* _syscall6() missing */ + +#endif /* _KLIBC_ARCHSYS_H */ diff --git a/klibc/klibc/arch/s390/setjmp.S b/klibc/klibc/arch/s390/setjmp.S new file mode 100644 index 0000000000..97132680ae --- /dev/null +++ b/klibc/klibc/arch/s390/setjmp.S @@ -0,0 +1,32 @@ +# +# arch/s390/setjmp.S +# +# setjmp/longjmp for the s390 architecture +# + + .text + .align 4 + .globl setjmp + .type setjmp, @function +setjmp: + stm %r6,%r15,0(%r2) # save all general registers + std %f4,40(%r2) # save fp registers f4 and f6 + std %f6,48(%r2) + lhi %r2,0 # return 0 + br %r14 + + .size setjmp,.-setjmp + + .text + .align 4 + .globl longjmp + .type longjmp, @function +longjmp: + lr %r1,%r2 # jmp_buf + lr %r2,%r3 # return value + ld %f6,48(%r1) # restore all saved registers + ld %f4,40(%r1) + lm %r6,%r15,0(%r1) + br %r14 # return to restored address + + .size longjmp,.-longjmp diff --git a/klibc/klibc/arch/s390x/MCONFIG b/klibc/klibc/arch/s390x/MCONFIG new file mode 100644 index 0000000000..1c8232bed5 --- /dev/null +++ b/klibc/klibc/arch/s390x/MCONFIG @@ -0,0 +1,13 @@ +# -*- makefile -*- +# +# arch/s390x/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +OPTFLAGS = -Os -fomit-frame-pointer +BITSIZE = 64 + +SHAREDFLAGS = -Ttext 0x40000200 diff --git a/klibc/klibc/arch/s390x/Makefile.inc b/klibc/klibc/arch/s390x/Makefile.inc new file mode 100644 index 0000000000..eff8f951ac --- /dev/null +++ b/klibc/klibc/arch/s390x/Makefile.inc @@ -0,0 +1,16 @@ +# -*- makefile -*- +# +# arch/s390x/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +ARCHOBJS = \ + arch/$(ARCH)/setjmp.o + +ARCHSOOBJS = $(patsubst %.o,%.lo,$(ARCHOBJS)) + + +archclean: diff --git a/klibc/klibc/arch/s390x/crt0.S b/klibc/klibc/arch/s390x/crt0.S new file mode 100644 index 0000000000..de35664904 --- /dev/null +++ b/klibc/klibc/arch/s390x/crt0.S @@ -0,0 +1,21 @@ +# +# arch/s390/crt0.S +# +# Does arch-specific initialization and invokes __libc_init +# with the appropriate arguments. +# +# See __static_init.c or __shared_init.c for the expected +# arguments. +# + + .text + .align 4 + .type _start,@function + .globl _start +_start: + lgr %r2,%r15 + lghi %r3,0 + aghi %r15,-160 + jg __libc_init + + .size _start,.-_start diff --git a/klibc/klibc/arch/s390x/include/klibc/archsetjmp.h b/klibc/klibc/arch/s390x/include/klibc/archsetjmp.h new file mode 100644 index 0000000000..dd3ed0d47c --- /dev/null +++ b/klibc/klibc/arch/s390x/include/klibc/archsetjmp.h @@ -0,0 +1,15 @@ +/* + * arch/s390x/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + uint64_t __gregs[10]; /* general registers r6-r15 */ + uint64_t __fpregs[4]; /* fp registers f1, f3, f5, f7 */ +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _SETJMP_H */ diff --git a/klibc/klibc/arch/s390x/include/klibc/archsys.h b/klibc/klibc/arch/s390x/include/klibc/archsys.h new file mode 100644 index 0000000000..15f7113bb4 --- /dev/null +++ b/klibc/klibc/arch/s390x/include/klibc/archsys.h @@ -0,0 +1,41 @@ +/* + * arch/s390x/include/klibc/archsys.h + * + * Architecture-specific syscall definitions + */ + +#ifndef _KLIBC_ARCHSYS_H +#define _KLIBC_ARCHSYS_H + +/* S/390X only has five syscall parameters, and uses a structure for + 6-argument syscalls. */ + +#ifndef _syscall6 + +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,\ + type4,arg4,type5,arg5,type6,arg6) \ +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ + type5 arg5, type6 arg6) { \ + unsigned long __arg[6] = { \ + (unsigned long) arg1, \ + (unsigned long) arg2, \ + (unsigned long) arg3, \ + (unsigned long) arg4, \ + (unsigned long) arg5, \ + (unsigned long) arg6 \ + }; \ + register void *__argp asm("2") = &__arg; \ + long __res; \ + __asm__ __volatile__ ( \ + " svc %b1\n" \ + " lgr %0,2" \ + : "=d" (__res) \ + : "i" (__NR_##name), \ + "d" (__argp) \ + : _svc_clobber); \ + __syscall_return(type, __res); \ +} + +#endif /* _syscall6() missing */ + +#endif /* _KLIBC_ARCHSYS_H */ diff --git a/klibc/klibc/arch/s390x/setjmp.S b/klibc/klibc/arch/s390x/setjmp.S new file mode 100644 index 0000000000..251c57d43a --- /dev/null +++ b/klibc/klibc/arch/s390x/setjmp.S @@ -0,0 +1,36 @@ +# +# arch/s390x/setjmp.S +# +# setjmp/longjmp for the s390x architecture +# + + .text + .align 4 + .globl setjmp + .type setjmp, @function +setjmp: + stmg %r6,%r15,0(%r2) # save all general registers + std %f1,80(%r2) # save fp registers f4 and f6 + std %f3,88(%r2) + std %f5,96(%r2) + std %f7,104(%r2) + lghi %r2,0 # return 0 + br %r14 + + .size setjmp,.-setjmp + + .text + .align 4 + .globl longjmp + .type longjmp, @function +longjmp: + lgr %r1,%r2 # jmp_buf + lgr %r2,%r3 # return value + ld %f7,104(%r1) # restore all saved registers + ld %f5,96(%r1) + ld %f3,88(%r1) + ld %f1,80(%r1) + lmg %r6,%r15,0(%r1) + br %r14 # return to restored address + + .size longjmp,.-longjmp diff --git a/klibc/klibc/arch/sh/MCONFIG b/klibc/klibc/arch/sh/MCONFIG new file mode 100644 index 0000000000..6cd4e5c839 --- /dev/null +++ b/klibc/klibc/arch/sh/MCONFIG @@ -0,0 +1,19 @@ +# -*- makefile -*- +# +# arch/sh/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +ARCHREGFLAGS = -m4 -mno-implicit-fp +OPTFLAGS = -Os -fomit-frame-pointer +BITSIZE = 32 + +# Extra linkflags when building the shared version of the library +# This address needs to be reachable using normal inter-module +# calls, and work on the memory models for this architecture +# 2 MB -- the normal starting point for text is 4 MB. +SHAREDFLAGS = -Ttext 0x00200200 + diff --git a/klibc/klibc/arch/sh/Makefile.inc b/klibc/klibc/arch/sh/Makefile.inc new file mode 100644 index 0000000000..16d7ea1e18 --- /dev/null +++ b/klibc/klibc/arch/sh/Makefile.inc @@ -0,0 +1,14 @@ +# -*- makefile -*- +# +# arch/sh/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +ARCHOBJS = arch/sh/setjmp.o + +ARCHSOOBJS = $(patsubst %.o,%.lo,$(ARCHOBJS)) + +archclean: diff --git a/klibc/klibc/arch/sh/crt0.S b/klibc/klibc/arch/sh/crt0.S new file mode 100644 index 0000000000..c9938a5612 --- /dev/null +++ b/klibc/klibc/arch/sh/crt0.S @@ -0,0 +1,28 @@ +# +# arch/sh/crt0.S +# +# void _start(void) +# { +# /* Divine up argc, argv, and envp */ +# environ = envp; +# exit(main(argc, argv, envp)); +# } +# + + .text + .align 2 + .type _start,#function + .globl _start + +_start: + mov r15, r4 + mov #0, r5 + mov.l 1f, r0 + + jsr @r0 + nop + + .align 2 +1: .long __libc_init + + .size _start,.-_start diff --git a/klibc/klibc/arch/sh/include/klibc/archsetjmp.h b/klibc/klibc/arch/sh/include/klibc/archsetjmp.h new file mode 100644 index 0000000000..28dd932fbc --- /dev/null +++ b/klibc/klibc/arch/sh/include/klibc/archsetjmp.h @@ -0,0 +1,22 @@ +/* + * arch/sh/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + unsigned long r8; + unsigned long r9; + unsigned long r10; + unsigned long r11; + unsigned long r12; + unsigned long r13; + unsigned long r14; + unsigned long r15; + unsigned long pr; +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _KLIBC_ARCHSETJMP_H */ diff --git a/klibc/klibc/arch/sh/include/klibc/archsys.h b/klibc/klibc/arch/sh/include/klibc/archsys.h new file mode 100644 index 0000000000..5f8050a536 --- /dev/null +++ b/klibc/klibc/arch/sh/include/klibc/archsys.h @@ -0,0 +1,12 @@ +/* + * arch/sh/include/klibc/archsys.h + * + * Architecture-specific syscall definitions + */ + +#ifndef _KLIBC_ARCHSYS_H +#define _KLIBC_ARCHSYS_H + +/* No special syscall definitions for this architecture */ + +#endif /* _KLIBC_ARCHSYS_H */ diff --git a/klibc/klibc/arch/sh/setjmp.S b/klibc/klibc/arch/sh/setjmp.S new file mode 100644 index 0000000000..63f760283f --- /dev/null +++ b/klibc/klibc/arch/sh/setjmp.S @@ -0,0 +1,65 @@ +# +# arch/sh/setjmp.S +# +# setjmp/longjmp for the SuperH architecture +# + +# +# The jmp_buf is assumed to contain the following, in order: +# +# r8 +# r9 +# r10 +# r11 +# r12 +# r13 +# r14 +# r15 +# pr +# + + .text + .align 2 + + .globl setjmp + .type setjmp, #function + +setjmp: + add #(9*4), r4 + sts.l pr, @-r4 + mov.l r15, @-r4 + mov.l r14, @-r4 + mov.l r13, @-r4 + mov.l r12, @-r4 + mov.l r11, @-r4 + mov.l r10, @-r4 + mov.l r9, @-r4 + mov.l r8, @-r4 + rts + mov #0, r0 + + .size setjmp,.-setjmp + + .align 2 + .globl longjmp + .type setjmp, #function + +longjmp: + mov.l @r4+, r8 + mov.l @r4+, r9 + mov.l @r4+, r10 + mov.l @r4+, r11 + mov.l @r4+, r12 + mov.l @r4+, r13 + mov.l @r4+, r14 + mov.l @r4+, r15 + lds.l @r4+, pr + mov r5, r0 + tst r0, r0 + bf 1f + mov #1, r0 ! in case val==0 +1: rts + nop + + .size longjmp,.-longjmp + diff --git a/klibc/klibc/arch/sparc/MCONFIG b/klibc/klibc/arch/sparc/MCONFIG new file mode 100644 index 0000000000..cb94f46c00 --- /dev/null +++ b/klibc/klibc/arch/sparc/MCONFIG @@ -0,0 +1,18 @@ +# -*- makefile -*- +# +# arch/sparc/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +OPTFLAGS = -Os -fomit-frame-pointer +BITSIZE = 32 + +# Extra linkflags when building the shared version of the library +# This address needs to be reachable using normal inter-module +# calls, and work on the memory models for this architecture +# Normal binaries start at 64K; the linker wants 64K alignment, +# and call instructions have a 30-bit signed offset, << 2. +SHAREDFLAGS = -Ttext 0x40000100 diff --git a/klibc/klibc/arch/sparc/Makefile.inc b/klibc/klibc/arch/sparc/Makefile.inc new file mode 100644 index 0000000000..0186810aca --- /dev/null +++ b/klibc/klibc/arch/sparc/Makefile.inc @@ -0,0 +1,44 @@ +# -*- makefile -*- +# +# arch/sparc/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +ARCHOBJS = \ + arch/$(ARCH)/sdiv.o \ + arch/$(ARCH)/udiv.o \ + arch/$(ARCH)/srem.o \ + arch/$(ARCH)/urem.o \ + arch/$(ARCH)/smul.o \ + arch/$(ARCH)/umul.o \ + arch/$(ARCH)/setjmp.o + +arch/$(ARCH)/sdiv.S: arch/$(ARCH)/divrem.m4 + @echo 'building $@ from $^' + @(echo "define(NAME,\`.div')define(OP,\`div')define(S,\`true')"; \ + cat $^) | m4 > $@ + @chmod 444 $@ + +arch/$(ARCH)/udiv.S: arch/$(ARCH)/divrem.m4 + @echo 'building $@ from $^' + @(echo "define(NAME,\`.udiv')define(OP,\`div')define(S,\`false')"; \ + cat $^) | m4 > $@ + @chmod 444 $@ + +arch/$(ARCH)/srem.S: arch/$(ARCH)/divrem.m4 + @echo 'building $@ from $^' + @(echo "define(NAME,\`.rem')define(OP,\`rem')define(S,\`true')"; \ + cat $^) | m4 > $@ + @chmod 444 $@ + +arch/$(ARCH)/urem.S: arch/$(ARCH)/divrem.m4 + @echo 'building $@ from $^' + @(echo "define(NAME,\`.urem')define(OP,\`rem')define(S,\`false')"; \ + cat $^) | m4 > $@ + @chmod 444 $@ + +archclean: + rm -f arch/$(ARCH)/?div.S arch/$(ARCH)/?rem.S diff --git a/klibc/klibc/arch/sparc/crt0.S b/klibc/klibc/arch/sparc/crt0.S new file mode 100644 index 0000000000..148cb4b4e9 --- /dev/null +++ b/klibc/klibc/arch/sparc/crt0.S @@ -0,0 +1,2 @@ +#define TARGET_PTR_SIZE 32 +#include "arch/sparc/crt0i.S" diff --git a/klibc/klibc/arch/sparc/crt0i.S b/klibc/klibc/arch/sparc/crt0i.S new file mode 100644 index 0000000000..97652a3090 --- /dev/null +++ b/klibc/klibc/arch/sparc/crt0i.S @@ -0,0 +1,100 @@ +! This file derived from the equivalent in newlib +! +! C run time start off + +! This file supports: +! +! - both 32bit pointer and 64bit pointer environments (at compile time) +! - an imposed stack bias (of 2047) (at run time) +! - medium/low and medium/anywhere code models (at run time) + +! Initial stack setup: +! +! bottom of stack (higher memory address) +! ... +! text of environment strings +! text of argument strings +! envp[envc] = 0 (4/8 bytes) +! ... +! env[0] (4/8 bytes) +! argv[argc] = 0 (4/8 bytes) +! ... +! argv[0] (4/8 bytes) +! argc (4/8 bytes) +! register save area (64 bits by 16 registers = 128 bytes) +! top of stack (%sp) + +! Stack Bias: +! +! It is the responsibility of the o/s to set this up. +! We handle both a 0 and 2047 value for the stack bias. + +! Medium/Anywhere code model support: +! +! In this model %g4 points to the start of the data segment. +! The text segment can go anywhere, but %g4 points to the *data* segment. +! It is up to the compiler/linker to get this right. +! +! Since this model is statically linked the start of the data segment +! is known at link time. Eg: +! +! sethi %hh(data_start), %g1 +! sethi %lm(data_start), %g4 +! or %g1, %hm(data_start), %g1 +! or %g4, %lo(data_start), %g4 +! sllx %g1, 32, %g1 +! or %g4, %g1, %g4 +! +! FIXME: For now we just assume 0. + +! FIXME: if %g1 contains a non-zero value, atexit() should be invoked +! with this value. + + + .text + .align 4 + .globl _start + .type _start, @function +_start: + clr %fp + +! We use %g4 even if the code model is Medium/Low (simplifies the code). + + clr %g4 ! Medium/Anywhere base reg + +! If there is a stack bias in effect, account for it in %g5. Then always +! add %g5 to stack references below. This way the code can be used with +! or without an imposed bias. + + andcc %sp, 1, %g5 + bz,a .LNoBias + nop + mov 2047, %g5 +.LNoBias: + add %sp, %g5, %g5 + +! On entry, the kernel leaves room for one register frame, but +! the C API wants more free space. Thus, we need to drop the stack +! pointer additionally. + +#if TARGET_PTR_SIZE == 32 + sub %sp, 32, %sp ! make room for incoming arguments +#else /* TARGET_PTR_SIZE == 64 */ + sub %sp, 64, %sp ! make room for incoming arguments +#endif + +! Set up pointers to the ELF data structure (argc, argv, ...) +! Pass as the first argument to __libc_init +#if TARGET_PTR_SIZE == 32 + add %g5, 0x40, %o0 +#else /* TARGET_PTR_SIZE == 64 */ + add %g5, 0x80, %o0 +#endif + + call __libc_init + mov %g1, %o1 ! This is the "atexit" pointer; + ! pass as the second argument to __libc_init + +! If __libc_init returns, something is hosed. Try an illegal insn. +! If that does not work, the o/s is hosed more than we are. + .long 0 diff --git a/klibc/klibc/arch/sparc/divrem.m4 b/klibc/klibc/arch/sparc/divrem.m4 new file mode 100644 index 0000000000..aa4171dd88 --- /dev/null +++ b/klibc/klibc/arch/sparc/divrem.m4 @@ -0,0 +1,276 @@ +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Header: divrem.m4,v 1.4 92/06/25 13:23:57 torek Exp + * $NetBSD: divrem.m4,v 1.4 1997/10/09 10:07:54 lukem Exp $ + */ + +/* + * Division and remainder, from Appendix E of the Sparc Version 8 + * Architecture Manual, with fixes from Gordon Irlam. + */ + +#if defined(LIBC_SCCS) && !defined(lint) + .asciz "@(#)divrem.m4 8.1 (Berkeley) 6/4/93" +#endif /* LIBC_SCCS and not lint */ + +/* + * Input: dividend and divisor in %o0 and %o1 respectively. + * + * m4 parameters: + * NAME name of function to generate + * OP OP=div => %o0 / %o1; OP=rem => %o0 % %o1 + * S S=true => signed; S=false => unsigned + * + * Algorithm parameters: + * N how many bits per iteration we try to get (4) + * WORDSIZE total number of bits (32) + * + * Derived constants: + * TWOSUPN 2^N, for label generation (m4 exponentiation currently broken) + * TOPBITS number of bits in the top `decade' of a number + * + * Important variables: + * Q the partial quotient under development (initially 0) + * R the remainder so far, initially the dividend + * ITER number of main division loop iterations required; + * equal to ceil(log2(quotient) / N). Note that this + * is the log base (2^N) of the quotient. + * V the current comparand, initially divisor*2^(ITER*N-1) + * + * Cost: + * Current estimate for non-large dividend is + * ceil(log2(quotient) / N) * (10 + 7N/2) + C + * A large dividend is one greater than 2^(31-TOPBITS) and takes a + * different path, as the upper bits of the quotient must be developed + * one bit at a time. + */ + +define(N, `4') +define(TWOSUPN, `16') +define(WORDSIZE, `32') +define(TOPBITS, eval(WORDSIZE - N*((WORDSIZE-1)/N))) + +define(dividend, `%o0') +define(divisor, `%o1') +define(Q, `%o2') +define(R, `%o3') +define(ITER, `%o4') +define(V, `%o5') + +/* m4 reminder: ifelse(a,b,c,d) => if a is b, then c, else d */ +define(T, `%g1') +define(SC, `%g7') +ifelse(S, `true', `define(SIGN, `%g6')') + +/* + * This is the recursive definition for developing quotient digits. + * + * Parameters: + * $1 the current depth, 1 <= $1 <= N + * $2 the current accumulation of quotient bits + * N max depth + * + * We add a new bit to $2 and either recurse or insert the bits in + * the quotient. R, Q, and V are inputs and outputs as defined above; + * the condition codes are expected to reflect the input R, and are + * modified to reflect the output R. + */ +define(DEVELOP_QUOTIENT_BITS, +` ! depth $1, accumulated bits $2 + bl L.$1.eval(TWOSUPN+$2) + srl V,1,V + ! remainder is positive + subcc R,V,R + ifelse($1, N, + ` b 9f + add Q, ($2*2+1), Q + ', ` DEVELOP_QUOTIENT_BITS(incr($1), `eval(2*$2+1)')') +L.$1.eval(TWOSUPN+$2): + ! remainder is negative + addcc R,V,R + ifelse($1, N, + ` b 9f + add Q, ($2*2-1), Q + ', ` DEVELOP_QUOTIENT_BITS(incr($1), `eval(2*$2-1)')') + ifelse($1, 1, `9:')') + +#include <machine/asm.h> +#include <machine/trap.h> + +FUNC(NAME) +ifelse(S, `true', +` ! compute sign of result; if neither is negative, no problem + orcc divisor, dividend, %g0 ! either negative? + bge 2f ! no, go do the divide + ifelse(OP, `div', + `xor divisor, dividend, SIGN', + `mov dividend, SIGN') ! compute sign in any case + tst divisor + bge 1f + tst dividend + ! divisor is definitely negative; dividend might also be negative + bge 2f ! if dividend not negative... + neg divisor ! in any case, make divisor nonneg +1: ! dividend is negative, divisor is nonnegative + neg dividend ! make dividend nonnegative +2: +') + ! Ready to divide. Compute size of quotient; scale comparand. + orcc divisor, %g0, V + bnz 1f + mov dividend, R + + ! Divide by zero trap. If it returns, return 0 (about as + ! wrong as possible, but that is what SunOS does...). + t ST_DIV0 + retl + clr %o0 + +1: + cmp R, V ! if divisor exceeds dividend, done + blu Lgot_result ! (and algorithm fails otherwise) + clr Q + sethi %hi(1 << (WORDSIZE - TOPBITS - 1)), T + cmp R, T + blu Lnot_really_big + clr ITER + + ! `Here the dividend is >= 2^(31-N) or so. We must be careful here, + ! as our usual N-at-a-shot divide step will cause overflow and havoc. + ! The number of bits in the result here is N*ITER+SC, where SC <= N. + ! Compute ITER in an unorthodox manner: know we need to shift V into + ! the top decade: so do not even bother to compare to R.' + 1: + cmp V, T + bgeu 3f + mov 1, SC + sll V, N, V + b 1b + inc ITER + + ! Now compute SC. + 2: addcc V, V, V + bcc Lnot_too_big + inc SC + + ! We get here if the divisor overflowed while shifting. + ! This means that R has the high-order bit set. + ! Restore V and subtract from R. + sll T, TOPBITS, T ! high order bit + srl V, 1, V ! rest of V + add V, T, V + b Ldo_single_div + dec SC + + Lnot_too_big: + 3: cmp V, R + blu 2b + nop + be Ldo_single_div + nop + /* NB: these are commented out in the V8-Sparc manual as well */ + /* (I do not understand this) */ + ! V > R: went too far: back up 1 step + ! srl V, 1, V + ! dec SC + ! do single-bit divide steps + ! + ! We have to be careful here. We know that R >= V, so we can do the + ! first divide step without thinking. BUT, the others are conditional, + ! and are only done if R >= 0. Because both R and V may have the high- + ! order bit set in the first step, just falling into the regular + ! division loop will mess up the first time around. + ! So we unroll slightly... + Ldo_single_div: + deccc SC + bl Lend_regular_divide + nop + sub R, V, R + mov 1, Q + b Lend_single_divloop + nop + Lsingle_divloop: + sll Q, 1, Q + bl 1f + srl V, 1, V + ! R >= 0 + sub R, V, R + b 2f + inc Q + 1: ! R < 0 + add R, V, R + dec Q + 2: + Lend_single_divloop: + deccc SC + bge Lsingle_divloop + tst R + b,a Lend_regular_divide + +Lnot_really_big: +1: + sll V, N, V + cmp V, R + bleu 1b + inccc ITER + be Lgot_result + dec ITER + + tst R ! set up for initial iteration +Ldivloop: + sll Q, N, Q + DEVELOP_QUOTIENT_BITS(1, 0) +Lend_regular_divide: + deccc ITER + bge Ldivloop + tst R + bl,a Lgot_result + ! non-restoring fixup here (one instruction only!) +ifelse(OP, `div', +` dec Q +', ` add R, divisor, R +') + +Lgot_result: +ifelse(S, `true', +` ! check to see if answer should be < 0 + tst SIGN + bl,a 1f + ifelse(OP, `div', `neg Q', `neg R') +1:') + retl + ifelse(OP, `div', `mov Q, %o0', `mov R, %o0') diff --git a/klibc/klibc/arch/sparc/include/klibc/archsetjmp.h b/klibc/klibc/arch/sparc/include/klibc/archsetjmp.h new file mode 100644 index 0000000000..92c1c74c9d --- /dev/null +++ b/klibc/klibc/arch/sparc/include/klibc/archsetjmp.h @@ -0,0 +1,16 @@ +/* + * arch/sparc/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + unsigned long __sp; + unsigned long __fp; + unsigned long __pc; +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _SETJMP_H */ diff --git a/klibc/klibc/arch/sparc/include/klibc/archsys.h b/klibc/klibc/arch/sparc/include/klibc/archsys.h new file mode 100644 index 0000000000..fe6e68df8a --- /dev/null +++ b/klibc/klibc/arch/sparc/include/klibc/archsys.h @@ -0,0 +1,65 @@ +/* + * arch/sparc/include/klibc/archsys.h + * + * Architecture-specific syscall definitions + */ + +#ifndef _KLIBC_ARCHSYS_H +#define _KLIBC_ARCHSYS_H + +/* fork and vfork return the "other process" pid in %o0 and an + "is child" flag in %o1... */ + +#define _syscall0_forkish(type,name) \ +type name(void) \ +{ \ +register long __g1 __asm__ ("g1") = __NR_##name; \ +register unsigned long __o0 __asm__ ("o0"); \ +register unsigned long __o1 __asm__ ("o1"); \ +__asm__ __volatile__ ("t 0x10\n\t" \ + "bcc 1f\n\t" \ + "mov %%o0, %0\n\t" \ + "sub %%g0, %%o0, %0\n\t" \ + "1:\n\t" \ + : "=r" (__o0), "=r" (__o1)\ + : "r" (__g1) \ + : "cc"); \ +if ((unsigned long)__o0 < (unsigned long)-255) \ + return (type)(__o0 & (__o1-1)); \ +errno = (int)-__o0; \ +return -1; \ +} + +/* SPARC seems to lack _syscall6() in its headers */ + +#ifndef _syscall6 + +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5,type6,arg6) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \ +{ \ +long __res; \ +register long __g1 __asm__ ("g1") = __NR_##name; \ +register long __o0 __asm__ ("o0") = (long)(arg1); \ +register long __o1 __asm__ ("o1") = (long)(arg2); \ +register long __o2 __asm__ ("o2") = (long)(arg3); \ +register long __o3 __asm__ ("o3") = (long)(arg4); \ +register long __o4 __asm__ ("o4") = (long)(arg5); \ +register long __o5 __asm__ ("o5") = (long)(arg6); \ +__asm__ __volatile__ ("t 0x10\n\t" \ + "bcc 1f\n\t" \ + "mov %%o0, %0\n\t" \ + "sub %%g0, %%o0, %0\n\t" \ + "1:\n\t" \ + : "=r" (__res), "=&r" (__o0) \ + : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__o4), "r" (__o5), "r" (__g1) \ + : "cc"); \ +if (__res < -255 || __res>=0) \ +return (type) __res; \ +errno = -__res; \ +return (type)-1; \ +} + +#endif /* _syscall6 missing */ + +#endif /* _KLIBC_ARCHSYS_H */ diff --git a/klibc/klibc/arch/sparc/include/machine/asm.h b/klibc/klibc/arch/sparc/include/machine/asm.h new file mode 100644 index 0000000000..b622bd8cf1 --- /dev/null +++ b/klibc/klibc/arch/sparc/include/machine/asm.h @@ -0,0 +1,192 @@ +/* $NetBSD: asm.h,v 1.14 2002/07/20 08:37:30 mrg Exp $ */ + +/* + * Copyright (c) 1994 Allen Briggs + * All rights reserved. + * + * Gleaned from locore.s and sun3 asm.h which had the following copyrights: + * locore.s: + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1982, 1990 The Regents of the University of California. + * sun3/include/asm.h: + * Copyright (c) 1993 Adam Glass + * Copyright (c) 1990 The Regents of the University of California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _ASM_H_ +#define _ASM_H_ + +/* Pull in CCFSZ, CC64FSZ, and BIAS from frame.h */ +#ifndef _LOCORE +#define _LOCORE +#endif +#include <machine/frame.h> + +#ifdef __ELF__ +#define _C_LABEL(name) name +#else +#ifdef __STDC__ +#define _C_LABEL(name) _ ## name +#else +#define _C_LABEL(name) _/**/name +#endif +#endif +#define _ASM_LABEL(name) name + +#ifdef PIC +/* + * PIC_PROLOGUE() is akin to the compiler generated function prologue for + * PIC code. It leaves the address of the Global Offset Table in DEST, + * clobbering register TMP in the process. + * + * We can use two code sequences. We can read the %pc or use the call + * instruction that saves the pc in %o7. Call requires the branch unit and + * IEU1, and clobbers %o7 which needs to be restored. This instruction + * sequence takes about 4 cycles due to instruction interdependence. Reading + * the pc takes 4 cycles to dispatch and is always dispatched alone. That + * sequence takes 7 cycles. + */ +#ifdef __arch64__ +#define PIC_PROLOGUE(dest,tmp) \ + mov %o7, tmp; \ + sethi %hi(_GLOBAL_OFFSET_TABLE_-4),dest; \ + call 0f; \ + or dest,%lo(_GLOBAL_OFFSET_TABLE_+4),dest; \ +0: \ + add dest,%o7,dest; \ + mov tmp, %o7 +#else +#define PIC_PROLOGUE(dest,tmp) \ + mov %o7,tmp; 3: call 4f; nop; 4: \ + sethi %hi(_C_LABEL(_GLOBAL_OFFSET_TABLE_)-(3b-.)),dest; \ + or dest,%lo(_C_LABEL(_GLOBAL_OFFSET_TABLE_)-(3b-.)),dest; \ + add dest,%o7,dest; mov tmp,%o7 +#endif + +/* + * PICCY_SET() does the equivalent of a `set var, %dest' instruction in + * a PIC-like way, but without involving the Global Offset Table. This + * only works for VARs defined in the same file *and* in the text segment. + */ +#ifdef __arch64__ +#define PICCY_SET(var,dest,tmp) \ + 3: rd %pc, tmp; add tmp,(var-3b),dest +#else +#define PICCY_SET(var,dest,tmp) \ + mov %o7,tmp; 3: call 4f; nop; 4: \ + add %o7,(var-3b),dest; mov tmp,%o7 +#endif +#else +#define PIC_PROLOGUE(dest,tmp) +#define PICCY_OFFSET(var,dest,tmp) +#endif + +#define FTYPE(x) .type x,@function +#define OTYPE(x) .type x,@object + +#define _ENTRY(name) \ + .align 4; .globl name; .proc 1; FTYPE(name); name: + +#ifdef GPROF +/* see _MCOUNT_ENTRY in profile.h */ +#ifdef __ELF__ +#ifdef __arch64__ +#define _PROF_PROLOGUE \ + .data; .align 8; 1: .uaword 0; .uaword 0; \ + .text; save %sp,-CC64FSZ,%sp; sethi %hi(1b),%o0; call _mcount; \ + or %o0,%lo(1b),%o0; restore +#else +#define _PROF_PROLOGUE \ + .data; .align 4; 1: .long 0; \ + .text; save %sp,-96,%sp; sethi %hi(1b),%o0; call _mcount; \ + or %o0,%lo(1b),%o0; restore +#endif +#else +#ifdef __arch64__ +#define _PROF_PROLOGUE \ + .data; .align 8; 1: .uaword 0; .uaword 0; \ + .text; save %sp,-CC64FSZ,%sp; sethi %hi(1b),%o0; call mcount; \ + or %o0,%lo(1b),%o0; restore +#else +#define _PROF_PROLOGUE \ + .data; .align 4; 1: .long 0; \ + .text; save %sp,-96,%sp; sethi %hi(1b),%o0; call mcount; \ + or %o0,%lo(1b),%o0; restore +#endif +#endif +#else +#define _PROF_PROLOGUE +#endif + +#define ENTRY(name) _ENTRY(_C_LABEL(name)); _PROF_PROLOGUE +#define ENTRY_NOPROFILE(name) _ENTRY(_C_LABEL(name)) +#define ASENTRY(name) _ENTRY(_ASM_LABEL(name)); _PROF_PROLOGUE +#define FUNC(name) ASENTRY(name) +#define RODATA(name) .align 4; .text; .globl _C_LABEL(name); \ + OTYPE(_C_LABEL(name)); _C_LABEL(name): + + +#define ASMSTR .asciz + +#define RCSID(name) .asciz name + +#ifdef __ELF__ +#define WEAK_ALIAS(alias,sym) \ + .weak alias; \ + alias = sym +#endif + +/* + * WARN_REFERENCES: create a warning if the specified symbol is referenced. + */ +#ifdef __ELF__ +#ifdef __STDC__ +#define WARN_REFERENCES(_sym,_msg) \ + .section .gnu.warning. ## _sym ; .ascii _msg ; .text +#else +#define WARN_REFERENCES(_sym,_msg) \ + .section .gnu.warning./**/_sym ; .ascii _msg ; .text +#endif /* __STDC__ */ +#else +#ifdef __STDC__ +#define __STRING(x) #x +#define WARN_REFERENCES(sym,msg) \ + .stabs msg ## ,30,0,0,0 ; \ + .stabs __STRING(_ ## sym) ## ,1,0,0,0 +#else +#define __STRING(x) "x" +#define WARN_REFERENCES(sym,msg) \ + .stabs msg,30,0,0,0 ; \ + .stabs __STRING(_/**/sym),1,0,0,0 +#endif /* __STDC__ */ +#endif /* __ELF__ */ + +#endif /* _ASM_H_ */ diff --git a/klibc/klibc/arch/sparc/include/machine/frame.h b/klibc/klibc/arch/sparc/include/machine/frame.h new file mode 100644 index 0000000000..b09175c7f4 --- /dev/null +++ b/klibc/klibc/arch/sparc/include/machine/frame.h @@ -0,0 +1,138 @@ +/* $NetBSD: frame.h,v 1.4 2001/12/04 00:05:05 darrenr Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)frame.h 8.1 (Berkeley) 6/11/93 + */ + +#if defined(_KERNEL_OPT) +#include "opt_sparc_arch.h" +#endif + +/* + * Sparc stack frame format. + * + * Note that the contents of each stack frame may be held only in + * machine register windows. In order to get an accurate picture + * of the frame, you must first force the kernel to write any such + * windows to the stack. + */ +#ifndef _LOCORE +#ifndef SUN4U +struct frame { + int32_t fr_local[8]; /* space to save locals (%l0..%l7) */ + int32_t fr_arg[6]; /* space to save arguments (%i0..%i5) */ + struct frame *fr_fp; /* space to save frame pointer (%i6) */ + int32_t fr_pc; /* space to save return pc (%i7) */ + /* + * SunOS reserves another 8 words here; this is pointless + * but we do it for compatibility. + */ + int32_t fr_xxx; /* `structure return pointer' (unused) */ + int32_t fr_argd[6]; /* `arg dump area' (lunacy) */ + int32_t fr_argx[1]; /* arg extension (args 7..n; variable size) */ +}; +#else +struct frame32 { + int32_t fr_local[8]; /* space to save locals (%l0..%l7) */ + int32_t fr_arg[6]; /* space to save arguments (%i0..%i5) */ + u_int32_t fr_fp; /* space to save frame pointer (%i6) */ + u_int32_t fr_pc; /* space to save return pc (%i7) */ + /* + * SunOS reserves another 8 words here; this is pointless + * but we do it for compatibility. + */ + int32_t fr_xxx; /* `structure return pointer' (unused) */ + int32_t fr_argd[6]; /* `arg dump area' (lunacy) */ + int32_t fr_argx[1]; /* arg extension (args 7..n; variable size) */ +}; +#endif +#endif + +/* + * CCFSZ (C Compiler Frame SiZe) is the size of a stack frame required if + * a function is to call C code. It should be just 64, but Sun defined + * their frame with space to hold arguments 0 through 5 (plus some junk), + * and varargs routines (such as kprintf) demand this, and gcc uses this + * area at times anyway. + */ +#define CCFSZ 96 + +/* + * Sparc v9 stack frame format. + * + * Note that the contents of each stack frame may be held only in + * machine register windows. In order to get an accurate picture + * of the frame, you must first force the kernel to write any such + * windows to the stack. + * + * V9 frames have an odd bias, so you can tall a v9 frame from + * a v8 frame by testing the stack pointer's lsb. + */ +#if !defined(_LOCORE) && !defined(_LIBC) +struct frame64 { + int64_t fr_local[8]; /* space to save locals (%l0..%l7) */ + int64_t fr_arg[6]; /* space to save arguments (%i0..%i5) */ + u_int64_t fr_fp; /* space to save frame pointer (%i6) */ + u_int64_t fr_pc; /* space to save return pc (%i7) */ + /* + * SVR4 reserves a bunch of extra stuff. + */ + int64_t fr_argd[6]; /* `register save area' (lunacy) */ + int64_t fr_argx[0]; /* arg extension (args 7..n; variable size) */ +}; + +#define v9next_frame(f) ((struct frame64*)(f->fr_fp+BIAS)) +#endif + +/* + * CC64FSZ (C Compiler 64-bit Frame SiZe) is the size of a stack frame used + * by the compiler in 64-bit mode. It is (16)*8; space for 8 ins, 8 outs. + */ +#define CC64FSZ 176 + +/* + * v9 stacks all have a bias of 2047 added to the %sp and %fp, so you can easily + * detect it by testing the register for an odd value. Why 2K-1 I don't know. + */ +#define BIAS (2048-1) + diff --git a/klibc/klibc/arch/sparc/include/machine/trap.h b/klibc/klibc/arch/sparc/include/machine/trap.h new file mode 100644 index 0000000000..42c3ef6ae2 --- /dev/null +++ b/klibc/klibc/arch/sparc/include/machine/trap.h @@ -0,0 +1,141 @@ +/* $NetBSD: trap.h,v 1.11 1999/01/20 00:15:08 pk Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)trap.h 8.1 (Berkeley) 6/11/93 + */ +/* + * Sun4m support by Aaron Brown, Harvard University. + * Changes Copyright (c) 1995 The President and Fellows of Harvard College. + * All rights reserved. + */ + +#ifndef _MACHINE_TRAP_H +#define _MACHINE_TRAP_H + +/* trap vec (pri) description */ +#define T_RESET 0x00 /* (1) not actually vectored; jumps to 0 */ +#define T_TEXTFAULT 0x01 /* (2) address fault during instr fetch */ +#define T_ILLINST 0x02 /* (3) illegal instruction */ +#define T_PRIVINST 0x03 /* (4) privileged instruction */ +#define T_FPDISABLED 0x04 /* (5) fp instr while fp disabled */ +#define T_WINOF 0x05 /* (6) register window overflow */ +#define T_WINUF 0x06 /* (7) register window underflow */ +#define T_ALIGN 0x07 /* (8) address not properly aligned */ +#define T_FPE 0x08 /* (9) floating point exception */ +#define T_DATAFAULT 0x09 /* (10) address fault during data fetch */ +#define T_TAGOF 0x0a /* (11) tag overflow */ +/* 0x0b unused */ +/* 0x0c unused */ +/* 0x0d unused */ +/* 0x0e unused */ +/* 0x0f unused */ +/* 0x10 unused */ +#define T_L1INT 0x11 /* (27) level 1 interrupt */ +#define T_L2INT 0x12 /* (26) level 2 interrupt */ +#define T_L3INT 0x13 /* (25) level 3 interrupt */ +#define T_L4INT 0x14 /* (24) level 4 interrupt */ +#define T_L5INT 0x15 /* (23) level 5 interrupt */ +#define T_L6INT 0x16 /* (22) level 6 interrupt */ +#define T_L7INT 0x17 /* (21) level 7 interrupt */ +#define T_L8INT 0x18 /* (20) level 8 interrupt */ +#define T_L9INT 0x19 /* (19) level 9 interrupt */ +#define T_L10INT 0x1a /* (18) level 10 interrupt */ +#define T_L11INT 0x1b /* (17) level 11 interrupt */ +#define T_L12INT 0x1c /* (16) level 12 interrupt */ +#define T_L13INT 0x1d /* (15) level 13 interrupt */ +#define T_L14INT 0x1e /* (14) level 14 interrupt */ +#define T_L15INT 0x1f /* (13) level 15 interrupt */ +/* 0x20 unused */ +/* through 0x23 unused */ +#define T_CPDISABLED 0x24 /* (5) coprocessor instr while disabled */ +#define T_UNIMPLFLUSH 0x25 /* Unimplemented FLUSH */ +/* through 0x27 unused */ +#define T_CPEXCEPTION 0x28 /* (9) coprocessor exception */ +/* 0x29 unused */ +#define T_IDIV0 0x2a /* divide by zero (from hw [su]div instr) */ +#define T_STOREBUFFAULT 0x2b /* SuperSPARC: Store buffer copy-back fault */ +/* 0x2c unused */ +/* through 0x7f unused */ + +/* beginning of `user' vectors (from trap instructions) - all priority 12 */ +#define T_SUN_SYSCALL 0x80 /* system call */ +#define T_BREAKPOINT 0x81 /* breakpoint `instruction' */ +#define T_DIV0 0x82 /* division routine was handed 0 */ +#define T_FLUSHWIN 0x83 /* flush windows */ +#define T_CLEANWIN 0x84 /* provide clean windows */ +#define T_RANGECHECK 0x85 /* ? */ +#define T_FIXALIGN 0x86 /* fix up unaligned accesses */ +#define T_INTOF 0x87 /* integer overflow ? */ +#define T_SVR4_SYSCALL 0x88 /* SVR4 system call */ +#define T_BSD_SYSCALL 0x89 /* BSD system call */ +#define T_KGDB_EXEC 0x8a /* for kernel gdb */ + +/* 0x8b..0xff are currently unallocated, except the following */ +#define T_SVR4_GETCC 0xa0 +#define T_SVR4_SETCC 0xa1 +#define T_SVR4_GETPSR 0xa2 +#define T_SVR4_SETPSR 0xa3 +#define T_SVR4_GETHRTIME 0xa4 +#define T_SVR4_GETHRVTIME 0xa5 +#define T_SVR4_GETHRESTIME 0xa7 + + +#ifdef _KERNEL /* pseudo traps for locore.s */ +#define T_RWRET -1 /* need first user window for trap return */ +#define T_AST -2 /* no-op, just needed reschedule or profile */ +#endif + +/* flags to system call (flags in %g1 along with syscall number) */ +#define SYSCALL_G2RFLAG 0x400 /* on success, return to %g2 rather than npc */ +#define SYSCALL_G7RFLAG 0x800 /* use %g7 as above (deprecated) */ + +/* + * `software trap' macros to keep people happy (sparc v8 manual says not + * to set the upper bits). + */ +#define ST_BREAKPOINT (T_BREAKPOINT & 0x7f) +#define ST_DIV0 (T_DIV0 & 0x7f) +#define ST_FLUSHWIN (T_FLUSHWIN & 0x7f) +#define ST_SYSCALL (T_SUN_SYSCALL & 0x7f) + +#endif /* _MACHINE_TRAP_H_ */ diff --git a/klibc/klibc/arch/sparc/setjmp.S b/klibc/klibc/arch/sparc/setjmp.S new file mode 100644 index 0000000000..f41ee2bf12 --- /dev/null +++ b/klibc/klibc/arch/sparc/setjmp.S @@ -0,0 +1,38 @@ +! +! setjmp.S +! +! Basic setjmp/longjmp +! +! This code was based on the equivalent code in NetBSD +! + +#include <machine/asm.h> +#include <machine/trap.h> + +! +! The jmp_buf contains the following entries: +! sp +! fp +! pc +! +ENTRY(setjmp) + st %sp,[%o0+0] ! Callers stack pointer + st %o7,[%o0+4] ! Return pc + st %fp,[%o0+8] ! Frame pointer + retl ! Return + clr %o0 ! ...0 + +ENTRY(longjmp) + sub %sp, 64, %sp ! set up a local stack frame +0: + t ST_FLUSHWIN ! flush register windows out to memory + ! + ! We restore the saved stack pointer to %fp, then issue + ! a restore instruction which will reload the register + ! window from the stack. + ! + ld [%o0+4], %o7 /* restore return pc */ + ld [%o0+0], %fp /* and stack pointer */ + + retl ! success, return %g6 + restore %o1, 0, %o0 diff --git a/klibc/klibc/arch/sparc/smul.S b/klibc/klibc/arch/sparc/smul.S new file mode 100644 index 0000000000..0eb218bbe8 --- /dev/null +++ b/klibc/klibc/arch/sparc/smul.S @@ -0,0 +1,160 @@ +/* $NetBSD: mul.S,v 1.3 1997/07/16 14:37:42 christos Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Header: mul.s,v 1.5 92/06/25 13:24:03 torek Exp + */ + +#include <machine/asm.h> +#if defined(LIBC_SCCS) && !defined(lint) +#if 0 + .asciz "@(#)mul.s 8.1 (Berkeley) 6/4/93" +#else + RCSID("$NetBSD: mul.S,v 1.3 1997/07/16 14:37:42 christos Exp $") +#endif +#endif /* LIBC_SCCS and not lint */ + +/* + * Signed multiply, from Appendix E of the Sparc Version 8 + * Architecture Manual. + * + * Returns %o0 * %o1 in %o1%o0 (i.e., %o1 holds the upper 32 bits of + * the 64-bit product). + * + * This code optimizes short (less than 13-bit) multiplies. + */ + +FUNC(.mul) + mov %o0, %y ! multiplier -> Y + andncc %o0, 0xfff, %g0 ! test bits 12..31 + be Lmul_shortway ! if zero, can do it the short way + andcc %g0, %g0, %o4 ! zero the partial product and clear N and V + + /* + * Long multiply. 32 steps, followed by a final shift step. + */ + mulscc %o4, %o1, %o4 ! 1 + mulscc %o4, %o1, %o4 ! 2 + mulscc %o4, %o1, %o4 ! 3 + mulscc %o4, %o1, %o4 ! 4 + mulscc %o4, %o1, %o4 ! 5 + mulscc %o4, %o1, %o4 ! 6 + mulscc %o4, %o1, %o4 ! 7 + mulscc %o4, %o1, %o4 ! 8 + mulscc %o4, %o1, %o4 ! 9 + mulscc %o4, %o1, %o4 ! 10 + mulscc %o4, %o1, %o4 ! 11 + mulscc %o4, %o1, %o4 ! 12 + mulscc %o4, %o1, %o4 ! 13 + mulscc %o4, %o1, %o4 ! 14 + mulscc %o4, %o1, %o4 ! 15 + mulscc %o4, %o1, %o4 ! 16 + mulscc %o4, %o1, %o4 ! 17 + mulscc %o4, %o1, %o4 ! 18 + mulscc %o4, %o1, %o4 ! 19 + mulscc %o4, %o1, %o4 ! 20 + mulscc %o4, %o1, %o4 ! 21 + mulscc %o4, %o1, %o4 ! 22 + mulscc %o4, %o1, %o4 ! 23 + mulscc %o4, %o1, %o4 ! 24 + mulscc %o4, %o1, %o4 ! 25 + mulscc %o4, %o1, %o4 ! 26 + mulscc %o4, %o1, %o4 ! 27 + mulscc %o4, %o1, %o4 ! 28 + mulscc %o4, %o1, %o4 ! 29 + mulscc %o4, %o1, %o4 ! 30 + mulscc %o4, %o1, %o4 ! 31 + mulscc %o4, %o1, %o4 ! 32 + mulscc %o4, %g0, %o4 ! final shift + + ! If %o0 was negative, the result is + ! (%o0 * %o1) + (%o1 << 32)) + ! We fix that here. + + tst %o0 + bge 1f + rd %y, %o0 + + ! %o0 was indeed negative; fix upper 32 bits of result by subtracting + ! %o1 (i.e., return %o4 - %o1 in %o1). + retl + sub %o4, %o1, %o1 + +1: + retl + mov %o4, %o1 + +Lmul_shortway: + /* + * Short multiply. 12 steps, followed by a final shift step. + * The resulting bits are off by 12 and (32-12) = 20 bit positions, + * but there is no problem with %o0 being negative (unlike above). + */ + mulscc %o4, %o1, %o4 ! 1 + mulscc %o4, %o1, %o4 ! 2 + mulscc %o4, %o1, %o4 ! 3 + mulscc %o4, %o1, %o4 ! 4 + mulscc %o4, %o1, %o4 ! 5 + mulscc %o4, %o1, %o4 ! 6 + mulscc %o4, %o1, %o4 ! 7 + mulscc %o4, %o1, %o4 ! 8 + mulscc %o4, %o1, %o4 ! 9 + mulscc %o4, %o1, %o4 ! 10 + mulscc %o4, %o1, %o4 ! 11 + mulscc %o4, %o1, %o4 ! 12 + mulscc %o4, %g0, %o4 ! final shift + + /* + * %o4 has 20 of the bits that should be in the low part of the + * result; %y has the bottom 12 (as %y's top 12). That is: + * + * %o4 %y + * +----------------+----------------+ + * | -12- | -20- | -12- | -20- | + * +------(---------+------)---------+ + * --hi-- ----low-part---- + * + * The upper 12 bits of %o4 should be sign-extended to form the + * high part of the product (i.e., highpart = %o4 >> 20). + */ + + rd %y, %o5 + sll %o4, 12, %o0 ! shift middle bits left 12 + srl %o5, 20, %o5 ! shift low bits right 20, zero fill at left + or %o5, %o0, %o0 ! construct low part of result + retl + sra %o4, 20, %o1 ! ... and extract high part of result diff --git a/klibc/klibc/arch/sparc/umul.S b/klibc/klibc/arch/sparc/umul.S new file mode 100644 index 0000000000..6a7193d217 --- /dev/null +++ b/klibc/klibc/arch/sparc/umul.S @@ -0,0 +1,193 @@ +/* $NetBSD: umul.S,v 1.3 1997/07/16 14:37:44 christos Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Header: umul.s,v 1.4 92/06/25 13:24:05 torek Exp + */ + +#include <machine/asm.h> +#if defined(LIBC_SCCS) && !defined(lint) +#if 0 + .asciz "@(#)umul.s 8.1 (Berkeley) 6/4/93" +#else + RCSID("$NetBSD: umul.S,v 1.3 1997/07/16 14:37:44 christos Exp $") +#endif +#endif /* LIBC_SCCS and not lint */ + +/* + * Unsigned multiply. Returns %o0 * %o1 in %o1%o0 (i.e., %o1 holds the + * upper 32 bits of the 64-bit product). + * + * This code optimizes short (less than 13-bit) multiplies. Short + * multiplies require 25 instruction cycles, and long ones require + * 45 instruction cycles. + * + * On return, overflow has occurred (%o1 is not zero) if and only if + * the Z condition code is clear, allowing, e.g., the following: + * + * call .umul + * nop + * bnz overflow (or tnz) + */ + +FUNC(.umul) + or %o0, %o1, %o4 + mov %o0, %y ! multiplier -> Y + andncc %o4, 0xfff, %g0 ! test bits 12..31 of *both* args + be Lmul_shortway ! if zero, can do it the short way + andcc %g0, %g0, %o4 ! zero the partial product and clear N and V + + /* + * Long multiply. 32 steps, followed by a final shift step. + */ + mulscc %o4, %o1, %o4 ! 1 + mulscc %o4, %o1, %o4 ! 2 + mulscc %o4, %o1, %o4 ! 3 + mulscc %o4, %o1, %o4 ! 4 + mulscc %o4, %o1, %o4 ! 5 + mulscc %o4, %o1, %o4 ! 6 + mulscc %o4, %o1, %o4 ! 7 + mulscc %o4, %o1, %o4 ! 8 + mulscc %o4, %o1, %o4 ! 9 + mulscc %o4, %o1, %o4 ! 10 + mulscc %o4, %o1, %o4 ! 11 + mulscc %o4, %o1, %o4 ! 12 + mulscc %o4, %o1, %o4 ! 13 + mulscc %o4, %o1, %o4 ! 14 + mulscc %o4, %o1, %o4 ! 15 + mulscc %o4, %o1, %o4 ! 16 + mulscc %o4, %o1, %o4 ! 17 + mulscc %o4, %o1, %o4 ! 18 + mulscc %o4, %o1, %o4 ! 19 + mulscc %o4, %o1, %o4 ! 20 + mulscc %o4, %o1, %o4 ! 21 + mulscc %o4, %o1, %o4 ! 22 + mulscc %o4, %o1, %o4 ! 23 + mulscc %o4, %o1, %o4 ! 24 + mulscc %o4, %o1, %o4 ! 25 + mulscc %o4, %o1, %o4 ! 26 + mulscc %o4, %o1, %o4 ! 27 + mulscc %o4, %o1, %o4 ! 28 + mulscc %o4, %o1, %o4 ! 29 + mulscc %o4, %o1, %o4 ! 30 + mulscc %o4, %o1, %o4 ! 31 + mulscc %o4, %o1, %o4 ! 32 + mulscc %o4, %g0, %o4 ! final shift + + + /* + * Normally, with the shift-and-add approach, if both numbers are + * positive you get the correct result. WIth 32-bit two's-complement + * numbers, -x is represented as + * + * x 32 + * ( 2 - ------ ) mod 2 * 2 + * 32 + * 2 + * + * (the `mod 2' subtracts 1 from 1.bbbb). To avoid lots of 2^32s, + * we can treat this as if the radix point were just to the left + * of the sign bit (multiply by 2^32), and get + * + * -x = (2 - x) mod 2 + * + * Then, ignoring the `mod 2's for convenience: + * + * x * y = xy + * -x * y = 2y - xy + * x * -y = 2x - xy + * -x * -y = 4 - 2x - 2y + xy + * + * For signed multiplies, we subtract (x << 32) from the partial + * product to fix this problem for negative multipliers (see mul.s). + * Because of the way the shift into the partial product is calculated + * (N xor V), this term is automatically removed for the multiplicand, + * so we don't have to adjust. + * + * But for unsigned multiplies, the high order bit wasn't a sign bit, + * and the correction is wrong. So for unsigned multiplies where the + * high order bit is one, we end up with xy - (y << 32). To fix it + * we add y << 32. + */ + tst %o1 + bl,a 1f ! if %o1 < 0 (high order bit = 1), + add %o4, %o0, %o4 ! %o4 += %o0 (add y to upper half) +1: rd %y, %o0 ! get lower half of product + retl + addcc %o4, %g0, %o1 ! put upper half in place and set Z for %o1==0 + +Lmul_shortway: + /* + * Short multiply. 12 steps, followed by a final shift step. + * The resulting bits are off by 12 and (32-12) = 20 bit positions, + * but there is no problem with %o0 being negative (unlike above), + * and overflow is impossible (the answer is at most 24 bits long). + */ + mulscc %o4, %o1, %o4 ! 1 + mulscc %o4, %o1, %o4 ! 2 + mulscc %o4, %o1, %o4 ! 3 + mulscc %o4, %o1, %o4 ! 4 + mulscc %o4, %o1, %o4 ! 5 + mulscc %o4, %o1, %o4 ! 6 + mulscc %o4, %o1, %o4 ! 7 + mulscc %o4, %o1, %o4 ! 8 + mulscc %o4, %o1, %o4 ! 9 + mulscc %o4, %o1, %o4 ! 10 + mulscc %o4, %o1, %o4 ! 11 + mulscc %o4, %o1, %o4 ! 12 + mulscc %o4, %g0, %o4 ! final shift + + /* + * %o4 has 20 of the bits that should be in the result; %y has + * the bottom 12 (as %y's top 12). That is: + * + * %o4 %y + * +----------------+----------------+ + * | -12- | -20- | -12- | -20- | + * +------(---------+------)---------+ + * -----result----- + * + * The 12 bits of %o4 left of the `result' area are all zero; + * in fact, all top 20 bits of %o4 are zero. + */ + + rd %y, %o5 + sll %o4, 12, %o0 ! shift middle bits left 12 + srl %o5, 20, %o5 ! shift low bits right 20 + or %o5, %o0, %o0 + retl + addcc %g0, %g0, %o1 ! %o1 = zero, and set Z diff --git a/klibc/klibc/arch/sparc64/MCONFIG b/klibc/klibc/arch/sparc64/MCONFIG new file mode 100644 index 0000000000..d490c63643 --- /dev/null +++ b/klibc/klibc/arch/sparc64/MCONFIG @@ -0,0 +1,21 @@ +# -*- makefile -*- +# +# arch/sparc64/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +ARCHREQFLAGS = -m64 -mptr64 +OPTFLAGS = -Os -fomit-frame-pointer +BITSIZE = 64 + +LDFLAGS = -m elf64_sparc + +# Extra linkflags when building the shared version of the library +# This address needs to be reachable using normal inter-module +# calls, and work on the memory models for this architecture +# Normal binaries start at 1 MB; the linker wants 1 MB alignment, +# and call instructions have a 30-bit signed offset, << 2. +SHAREDFLAGS = -Ttext 0x80000200 diff --git a/klibc/klibc/arch/sparc64/Makefile.inc b/klibc/klibc/arch/sparc64/Makefile.inc new file mode 100644 index 0000000000..d59f9878e9 --- /dev/null +++ b/klibc/klibc/arch/sparc64/Makefile.inc @@ -0,0 +1,13 @@ +# -*- makefile -*- +# +# arch/sparc64/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +ARCHOBJS = \ + arch/$(ARCH)/setjmp.o + +archclean: diff --git a/klibc/klibc/arch/sparc64/crt0.S b/klibc/klibc/arch/sparc64/crt0.S new file mode 100644 index 0000000000..23af82ecc4 --- /dev/null +++ b/klibc/klibc/arch/sparc64/crt0.S @@ -0,0 +1,2 @@ +#define TARGET_PTR_SIZE 64 +#include "arch/sparc/crt0i.S" diff --git a/klibc/klibc/arch/sparc64/include/klibc/archsetjmp.h b/klibc/klibc/arch/sparc64/include/klibc/archsetjmp.h new file mode 100644 index 0000000000..022a31e542 --- /dev/null +++ b/klibc/klibc/arch/sparc64/include/klibc/archsetjmp.h @@ -0,0 +1,16 @@ +/* + * arch/sparc64/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + unsigned long __sp; + unsigned long __fp; + unsigned long __pc; +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _SETJMP_H */ diff --git a/klibc/klibc/arch/sparc64/include/klibc/archsys.h b/klibc/klibc/arch/sparc64/include/klibc/archsys.h new file mode 100644 index 0000000000..651e4f7f09 --- /dev/null +++ b/klibc/klibc/arch/sparc64/include/klibc/archsys.h @@ -0,0 +1,157 @@ +/* + * arch/sparc64/include/klibc/archsys.h + * + * Architecture-specific syscall definitions + */ + +#ifndef _KLIBC_ARCHSYS_H +#define _KLIBC_ARCHSYS_H + +/* The Linux 2.5.31 SPARC64 syscall macros are just plain broken */ + +#undef _syscall0 +#undef _syscall1 +#undef _syscall2 +#undef _syscall3 +#undef _syscall4 +#undef _syscall5 +#undef _syscall6 + +#define _syscall0(type,name) \ +type name (void) \ +{ \ + register unsigned long __g1 __asm__ ("g1") = __NR_##name; \ + register unsigned long __ret __asm__("o0"); \ + __asm__ __volatile__ ("t 0x6d\n\t" \ + "bcs,a %%xcc, 1f\n\t" \ + " st %0,%1\n\t" \ + "1:" \ + "movcs %%xcc,-1,%0\n" \ + : "=&r" (__ret), "+m" (errno) \ + : "r" (__g1) \ + : "cc"); \ + return (type) __ret; \ +} + +#define _syscall1(type,name,type1,arg1) \ +type name (type1 arg1) \ +{ \ + register unsigned long __g1 __asm__ ("g1") = __NR_##name; \ + register unsigned long __ret __asm__("o0"); \ + type1 __o0 = (arg1); \ + __asm__ __volatile__ ("t 0x6d\n\t" \ + "bcs,a %%xcc, 1f\n\t" \ + " st %0,%1\n\t" \ + "1:" \ + "movcs %%xcc,-1,%0\n" \ + : "=&r" (__ret), "+m" (errno) \ + : "0" (__o0), "r" (__g1) \ + : "cc"); \ + return (type) __ret; \ +} + +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name (type1 arg1,type2 arg2) \ +{ \ + register unsigned long __g1 __asm__ ("g1") = __NR_##name; \ + register unsigned long __ret __asm__("o0"); \ + type1 __o0 = (arg1); \ + register type2 __o1 __asm__ ("o1") = (arg2); \ + __asm__ __volatile__ ("t 0x6d\n\t" \ + "bcs,a %%xcc, 1f\n\t" \ + " st %0,%1\n\t" \ + "1:" \ + "movcs %%xcc,-1,%0\n" \ + : "=&r" (__ret), "+m" (errno) \ + : "0" (__o0), "r" (__o1), "r" (__g1) \ + : "cc"); \ + return (type) __ret; \ +} + +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name (type1 arg1,type2 arg2,type3 arg3) \ +{ \ + register unsigned long __g1 __asm__ ("g1") = __NR_##name; \ + register unsigned long __ret __asm__("o0"); \ + type1 __o0 = (arg1); \ + register type2 __o1 __asm__ ("o1") = (arg2); \ + register type3 __o2 __asm__ ("o2") = (arg3); \ + __asm__ __volatile__ ("t 0x6d\n\t" \ + "bcs,a %%xcc, 1f\n\t" \ + " st %0,%1\n\t" \ + "1:" \ + "movcs %%xcc,-1,%0\n" \ + : "=&r" (__ret), "+m" (errno) \ + : "0" (__o0), "r" (__o1), "r" (__o2), "r" (__g1) \ + : "cc"); \ + return (type) __ret; \ +} + +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \ +{ \ + register unsigned long __g1 __asm__ ("g1") = __NR_##name; \ + register unsigned long __ret __asm__("o0"); \ + type1 __o0 = (arg1); \ + register type2 __o1 __asm__ ("o1") = (arg2); \ + register type3 __o2 __asm__ ("o2") = (arg3); \ + register type4 __o3 __asm__ ("o3") = (arg4); \ + __asm__ __volatile__ ("t 0x6d\n\t" \ + "bcs,a %%xcc, 1f\n\t" \ + " st %0,%1\n\t" \ + "1:" \ + "movcs %%xcc,-1,%0\n" \ + : "=&r" (__ret), "+m" (errno) \ + : "0" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__g1) \ + : "cc"); \ + return (type) __ret; \ +} + +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,\ + type5,arg5) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ +{ \ + register unsigned long __g1 __asm__ ("g1") = __NR_##name; \ + register unsigned long __ret __asm__("o0"); \ + type1 __o0 = (arg1); \ + register type2 __o1 __asm__ ("o1") = (arg2); \ + register type3 __o2 __asm__ ("o2") = (arg3); \ + register type4 __o3 __asm__ ("o3") = (arg4); \ + register type5 __o4 __asm__ ("o4") = (arg5); \ + __asm__ __volatile__ ("t 0x6d\n\t" \ + "bcs,a %%xcc, 1f\n\t" \ + " st %0,%1\n\t" \ + "1:" \ + "movcs %%xcc,-1,%0\n" \ + : "=&r" (__ret), "+m" (errno) \ + : "0" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__o4), \ + "r" (__g1) \ + : "cc"); \ + return (type) __ret; \ +} + +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5,type6,arg6) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \ +{ \ + register unsigned long __g1 __asm__ ("g1") = __NR_##name; \ + register unsigned long __ret __asm__("o0"); \ + type1 __o0 = (arg1); \ + register type2 __o1 __asm__ ("o1") = (arg2); \ + register type3 __o2 __asm__ ("o2") = (arg3); \ + register type4 __o3 __asm__ ("o3") = (arg4); \ + register type5 __o4 __asm__ ("o4") = (arg5); \ + register type6 __o5 __asm__ ("o5") = (arg6); \ + __asm__ __volatile__ ("t 0x6d\n\t" \ + "bcs,a %%xcc, 1f\n\t" \ + " st %0,%1\n\t" \ + "1:" \ + "movcs %%xcc,-1,%0\n" \ + : "=&r" (__ret), "+m" (errno) \ + : "0" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__o4), \ + "r" (__o5), "r" (__g1) \ + : "cc"); \ + return (type) __ret; \ +} + +#endif /* _KLIBC_ARCHSYS_H */ diff --git a/klibc/klibc/arch/sparc64/setjmp.S b/klibc/klibc/arch/sparc64/setjmp.S new file mode 100644 index 0000000000..b04d47faab --- /dev/null +++ b/klibc/klibc/arch/sparc64/setjmp.S @@ -0,0 +1,55 @@ +! +! setjmp.S +! +! Basic setjmp/longjmp +! +! This code was based on the equivalent code in NetBSD +! + +! +! The jmp_buf contains the following entries: +! sp +! fp +! pc +! + .text + .align 4 + .global setjmp + .type setjmp, @function +setjmp: + stx %sp,[%o0+0] ! Callers stack pointer + stx %o7,[%o0+8] ! Return pc + stx %fp,[%o0+16] ! Frame pointer + retl ! Return + clr %o0 ! ...0 + + .size setjmp,.-setjmp + + + .globl longjmp + .type longjmp, @function +longjmp: + mov %o1, %g4 ! save return value + mov %o0, %g1 ! save target + ldx [%g1+16],%g5 ! get callers frame +1: + cmp %fp, %g5 ! compare against desired frame + bl,a 1b ! if below... + restore ! pop frame and loop + be,a 2f ! if there... + ldx [%g1+0],%o2 ! fetch return %sp + +.Lbotch: + unimp 0 ! ... error ... + +2: + cmp %o2, %sp ! %sp must not decrease + bl .Lbotch + nop + mov %o2, %sp ! it is OK, put it in place + + ldx [%g1+8],%o3 ! fetch %pc + jmp %o3 + 8 ! if sucess... + mov %g4,%o0 ! return %g4 + + .size longjmp,.-longjmp diff --git a/klibc/klibc/arch/x86_64/MCONFIG b/klibc/klibc/arch/x86_64/MCONFIG new file mode 100644 index 0000000000..ecb14ccb70 --- /dev/null +++ b/klibc/klibc/arch/x86_64/MCONFIG @@ -0,0 +1,16 @@ +# -*- makefile -*- +# +# arch/x86-64/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# +# Blatantly copied and modified from i386 version by Mats Petersson, AMD. +# + +ARCHREQFLAGS = -m64 +OPTFLAGS = -Os -fomit-frame-pointer -falign-functions=0 -falign-jumps=0 -falign-loops=0 +BITSIZE = 64 +LDFLAGS = -m elf_x86_64 + diff --git a/klibc/klibc/arch/x86_64/Makefile.inc b/klibc/klibc/arch/x86_64/Makefile.inc new file mode 100644 index 0000000000..c84443f4e1 --- /dev/null +++ b/klibc/klibc/arch/x86_64/Makefile.inc @@ -0,0 +1,16 @@ +# -*- makefile -*- +# +# arch/x86_64/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +ARCHOBJS = \ + arch/$(ARCH)/exits.o \ + arch/$(ARCH)/setjmp.o + +ARCHSOOBJS = $(patsubst %.o,%.lo,$(ARCHOBJS)) + +archclean: diff --git a/klibc/klibc/arch/x86_64/crt0.S b/klibc/klibc/arch/x86_64/crt0.S new file mode 100644 index 0000000000..c562708d0f --- /dev/null +++ b/klibc/klibc/arch/x86_64/crt0.S @@ -0,0 +1,22 @@ +# +# arch/x86_64/crt0.S +# +# Does arch-specific initialization and invokes __libc_init +# with the appropriate arguments. +# +# See __static_init.c or __shared_init.c for the expected +# arguments. +# + + .text + .align 4 + .type _start,@function + .globl _start +_start: + movq %rsp,%rdi # Offset of the ELF data structure + movq %rdx,%rsi # The atexit() pointer (if any) + call __libc_init + # We should never get here... + hlt + + .size _start,.-_start diff --git a/klibc/klibc/arch/x86_64/exits.S b/klibc/klibc/arch/x86_64/exits.S new file mode 100644 index 0000000000..618f4fb585 --- /dev/null +++ b/klibc/klibc/arch/x86_64/exits.S @@ -0,0 +1,35 @@ +# +# exit and _exit get included in *every* program, and gcc generates +# horrible code for them. Yes, this only saves a few bytes, but +# it does it in every program. +# + +#include <asm/unistd.h> + + .data + .align 8 + .globl __exit_handler + .type __exit_handler,@object +__exit_handler: + .quad _exit + .size __exit_handler,8 + + .text + .align 8 + .globl exit + .type exit,@function +exit: + jmp *(__exit_handler) + .size exit,.-exit + + /* No need to save any registers... we're exiting! */ + .text + .align 4 + .globl _exit + .type _exit,@function +_exit: + movl $__NR_exit,%eax + /* The argument is already in %rdi */ + syscall + .size _exit,.-exit + diff --git a/klibc/klibc/arch/x86_64/include/klibc/archsetjmp.h b/klibc/klibc/arch/x86_64/include/klibc/archsetjmp.h new file mode 100644 index 0000000000..90d0a0d263 --- /dev/null +++ b/klibc/klibc/arch/x86_64/include/klibc/archsetjmp.h @@ -0,0 +1,21 @@ +/* + * arch/x86_64/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + unsigned long __rbx; + unsigned long __rsp; + unsigned long __rbp; + unsigned long __r12; + unsigned long __r13; + unsigned long __r14; + unsigned long __r15; + unsigned long __rip; +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _SETJMP_H */ diff --git a/klibc/klibc/arch/x86_64/include/klibc/archsys.h b/klibc/klibc/arch/x86_64/include/klibc/archsys.h new file mode 100644 index 0000000000..3bd8b0a5d9 --- /dev/null +++ b/klibc/klibc/arch/x86_64/include/klibc/archsys.h @@ -0,0 +1,32 @@ +/* + * arch/x86_64/include/klibc/archsys.h + * + * Architecture-specific syscall definitions + */ + +#ifndef _KLIBC_ARCHSYS_H +#define _KLIBC_ARCHSYS_H + +/* x86-64 seems to miss _syscall6() from its headers */ + +#ifndef _syscall6 + +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5,type6,arg6) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \ +{ \ +long __res; \ +register type4 __r10 asm("%r10") = arg4; \ +register type5 __r8 asm("%r8") = arg5; \ +register type6 __r9 asm("%r9") = arg6; \ +__asm__ volatile (__syscall \ + : "=a" (__res) \ + : "0" (__NR_##name),"D" (arg1),"S" (arg2), \ + "d" (arg3),"r" (__r10),"r" (__r8), "r" (__r9) \ + : __syscall_clobber); \ +__syscall_return(type,__res); \ +} + +#endif /* _syscall6 missing */ + +#endif /* _KLIBC_ARCHSYS_H */ diff --git a/klibc/klibc/arch/x86_64/setjmp.S b/klibc/klibc/arch/x86_64/setjmp.S new file mode 100644 index 0000000000..45f547b404 --- /dev/null +++ b/klibc/klibc/arch/x86_64/setjmp.S @@ -0,0 +1,54 @@ +# +# arch/x86_64/setjmp.S +# +# setjmp/longjmp for the x86-64 architecture +# + +# +# The jmp_buf is assumed to contain the following, in order: +# %rbx +# %rsp (post-return) +# %rbp +# %r12 +# %r13 +# %r14 +# %r15 +# <return address> +# + + .text + .align 4 + .globl setjmp + .type setjmp, @function +setjmp: + pop %rsi # Return address, and adjust the stack + xorl %eax,%eax # Return value + movq %rbx,(%rdi) + movq %rsp,8(%rdi) # Post-return %rsp! + push %rsi # Make the call/return stack happy + movq %rbp,16(%rdi) + movq %r12,24(%rdi) + movq %r13,32(%rdi) + movq %r14,40(%rdi) + movq %r15,48(%rdi) + movq %rsi,56(%rdi) # Return address + ret + + .size setjmp,.-setjmp + + .text + .align 4 + .globl longjmp + .type longjmp, @function +longjmp: + movl %esi,%eax # Return value (int) + movq (%rdi),%rbx + movq 8(%rdi),%rsp + movq 16(%rdi),%rbp + movq 24(%rdi),%r12 + movq 32(%rdi),%r13 + movq 40(%rdi),%r14 + movq 48(%rdi),%r15 + jmp *56(%rdi) + + .size longjmp,.-longjmp diff --git a/klibc/klibc/assert.c b/klibc/klibc/assert.c new file mode 100644 index 0000000000..6d3ff238c9 --- /dev/null +++ b/klibc/klibc/assert.c @@ -0,0 +1,13 @@ +/* + * assert.c + */ + +#include <stdlib.h> +#include <stdio.h> +#include <assert.h> + +void __assert_fail(const char *expr, const char *file, unsigned int line) +{ + printf("Assertion %s failed, file %s, line %u\n", expr, file, line); + abort(); +} diff --git a/klibc/klibc/atexit.c b/klibc/klibc/atexit.c new file mode 100644 index 0000000000..078dd8b211 --- /dev/null +++ b/klibc/klibc/atexit.c @@ -0,0 +1,10 @@ +/* + * atexit.c + */ + +#include <stdlib.h> + +int atexit(void (*fctn)(void)) +{ + return on_exit((void (*)(int, void *))fctn, NULL); +} diff --git a/klibc/klibc/atexit.h b/klibc/klibc/atexit.h new file mode 100644 index 0000000000..a60d641e23 --- /dev/null +++ b/klibc/klibc/atexit.h @@ -0,0 +1,19 @@ +/* + * atexit.h + * + * atexit()/on_exit() internal definitions + */ + +#ifndef ATEXIT_H +#define ATEXIT_H + +struct atexit { + void (*fctn)(int, void *); + void *arg; /* on_exit() parameter */ + struct atexit *next; +}; + +extern struct atexit *__atexit_list; + +#endif /* ATEXIT_H */ + diff --git a/klibc/klibc/atoi.c b/klibc/klibc/atoi.c new file mode 100644 index 0000000000..a6ec0bf778 --- /dev/null +++ b/klibc/klibc/atoi.c @@ -0,0 +1,3 @@ +#define TYPE int +#define NAME atoi +#include "atox.c" diff --git a/klibc/klibc/atol.c b/klibc/klibc/atol.c new file mode 100644 index 0000000000..e65484e7f1 --- /dev/null +++ b/klibc/klibc/atol.c @@ -0,0 +1,3 @@ +#define TYPE long +#define NAME atol +#include "atox.c" diff --git a/klibc/klibc/atoll.c b/klibc/klibc/atoll.c new file mode 100644 index 0000000000..25df79e1bf --- /dev/null +++ b/klibc/klibc/atoll.c @@ -0,0 +1,3 @@ +#define TYPE long long +#define NAME atoll +#include "atox.c" diff --git a/klibc/klibc/atox.c b/klibc/klibc/atox.c new file mode 100644 index 0000000000..56f8d93b40 --- /dev/null +++ b/klibc/klibc/atox.c @@ -0,0 +1,14 @@ +/* + * atox.c + * + * atoi(), atol(), atoll() + */ + +#include <inttypes.h> +#include <stdlib.h> +#include <stdio.h> + +TYPE NAME (const char *nptr) +{ + return (TYPE) strntoumax(nptr, (char **)NULL, 10, ~(size_t)0); +} diff --git a/klibc/klibc/brk.c b/klibc/klibc/brk.c new file mode 100644 index 0000000000..0a08c4e1c5 --- /dev/null +++ b/klibc/klibc/brk.c @@ -0,0 +1,24 @@ +/* brk.c - Change data segment size */ + +/* Written 2000 by Werner Almesberger */ + + +#include <stddef.h> +#include <unistd.h> +#include <sys/types.h> + +char *__current_brk; /* Common with sbrk.c */ + +/* + * The Linux brk() isn't what most people expect, so we call the + * system call __brk() and provide a wrapper. + */ +int brk(void *end_data_segment) +{ + char *new_brk; + + new_brk = __brk(end_data_segment); + if (new_brk != end_data_segment) return -1; + __current_brk = new_brk; + return 0; +} diff --git a/klibc/klibc/bsd_signal.c b/klibc/klibc/bsd_signal.c new file mode 100644 index 0000000000..9acc867a36 --- /dev/null +++ b/klibc/klibc/bsd_signal.c @@ -0,0 +1,11 @@ +/* + * bsd_signal.c + */ + +#include <signal.h> + +__sighandler_t bsd_signal(int signum, __sighandler_t handler) +{ + /* BSD signal() semantics */ + return __signal(signum, handler, SA_RESTART); +} diff --git a/klibc/klibc/calloc.c b/klibc/klibc/calloc.c new file mode 100644 index 0000000000..228a1b70e4 --- /dev/null +++ b/klibc/klibc/calloc.c @@ -0,0 +1,21 @@ +/* + * calloc.c + */ + +#include <stdlib.h> +#include <string.h> + +/* FIXME: This should look for multiplication overflow */ + +void *calloc(size_t nmemb, size_t size) +{ + void *ptr; + + size *= nmemb; + ptr = malloc(size); + if ( ptr ) + memset(ptr, 0, size); + + return ptr; +} + diff --git a/klibc/klibc/closelog.c b/klibc/klibc/closelog.c new file mode 100644 index 0000000000..2359d4f92b --- /dev/null +++ b/klibc/klibc/closelog.c @@ -0,0 +1,18 @@ +/* + * closelog.c + */ + +#include <syslog.h> +#include <unistd.h> + +extern int __syslog_fd; + +void closelog(void) +{ + int logfd = __syslog_fd; + + if ( logfd != -1 ) { + close(logfd); + __syslog_fd = -1; + } +} diff --git a/klibc/klibc/creat.c b/klibc/klibc/creat.c new file mode 100644 index 0000000000..9bd22172d4 --- /dev/null +++ b/klibc/klibc/creat.c @@ -0,0 +1,12 @@ +/* + * creat.c + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +int creat(const char *pathname, mode_t mode) +{ + return open(pathname, O_CREAT|O_WRONLY|O_TRUNC, mode); +} diff --git a/klibc/klibc/ctypes.c b/klibc/klibc/ctypes.c new file mode 100644 index 0000000000..a9398b8071 --- /dev/null +++ b/klibc/klibc/ctypes.c @@ -0,0 +1,281 @@ +/* + * ctypes.c + * + * This is the array that defines <ctype.h> classes. + * This assumes ISO 8859-1. + */ + +#include <ctype.h> + +const unsigned char __ctypes[257] = { + 0, /* EOF */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + __ctype_space, /* BS */ + __ctype_space, /* TAB */ + __ctype_space, /* LF */ + __ctype_space, /* VT */ + __ctype_space, /* FF */ + __ctype_space, /* CR */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + + __ctype_space|__ctype_print, /* space */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + + __ctype_digit|__ctype_xdigit|__ctype_print, /* digit */ + __ctype_digit|__ctype_xdigit|__ctype_print, /* digit */ + __ctype_digit|__ctype_xdigit|__ctype_print, /* digit */ + __ctype_digit|__ctype_xdigit|__ctype_print, /* digit */ + __ctype_digit|__ctype_xdigit|__ctype_print, /* digit */ + __ctype_digit|__ctype_xdigit|__ctype_print, /* digit */ + __ctype_digit|__ctype_xdigit|__ctype_print, /* digit */ + __ctype_digit|__ctype_xdigit|__ctype_print, /* digit */ + __ctype_digit|__ctype_xdigit|__ctype_print, /* digit */ + __ctype_digit|__ctype_xdigit|__ctype_print, /* digit */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_upper|__ctype_print|__ctype_xdigit, /* A-F */ + __ctype_upper|__ctype_print|__ctype_xdigit, /* A-F */ + __ctype_upper|__ctype_print|__ctype_xdigit, /* A-F */ + __ctype_upper|__ctype_print|__ctype_xdigit, /* A-F */ + __ctype_upper|__ctype_print|__ctype_xdigit, /* A-F */ + __ctype_upper|__ctype_print|__ctype_xdigit, /* A-F */ + __ctype_upper|__ctype_print, /* G-Z */ + __ctype_upper|__ctype_print, /* G-Z */ + __ctype_upper|__ctype_print, /* G-Z */ + __ctype_upper|__ctype_print, /* G-Z */ + __ctype_upper|__ctype_print, /* G-Z */ + __ctype_upper|__ctype_print, /* G-Z */ + __ctype_upper|__ctype_print, /* G-Z */ + __ctype_upper|__ctype_print, /* G-Z */ + __ctype_upper|__ctype_print, /* G-Z */ + + __ctype_upper|__ctype_print, /* G-Z */ + __ctype_upper|__ctype_print, /* G-Z */ + __ctype_upper|__ctype_print, /* G-Z */ + __ctype_upper|__ctype_print, /* G-Z */ + __ctype_upper|__ctype_print, /* G-Z */ + __ctype_upper|__ctype_print, /* G-Z */ + __ctype_upper|__ctype_print, /* G-Z */ + __ctype_upper|__ctype_print, /* G-Z */ + __ctype_upper|__ctype_print, /* G-Z */ + __ctype_upper|__ctype_print, /* G-Z */ + __ctype_upper|__ctype_print, /* G-Z */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_lower|__ctype_print|__ctype_xdigit, /* a-f */ + __ctype_lower|__ctype_print|__ctype_xdigit, /* a-f */ + __ctype_lower|__ctype_print|__ctype_xdigit, /* a-f */ + __ctype_lower|__ctype_print|__ctype_xdigit, /* a-f */ + __ctype_lower|__ctype_print|__ctype_xdigit, /* a-f */ + __ctype_lower|__ctype_print|__ctype_xdigit, /* a-f */ + __ctype_lower|__ctype_print, /* g-z */ + __ctype_lower|__ctype_print, /* g-z */ + __ctype_lower|__ctype_print, /* g-z */ + __ctype_lower|__ctype_print, /* g-z */ + __ctype_lower|__ctype_print, /* g-z */ + __ctype_lower|__ctype_print, /* g-z */ + __ctype_lower|__ctype_print, /* g-z */ + __ctype_lower|__ctype_print, /* g-z */ + __ctype_lower|__ctype_print, /* g-z */ + + __ctype_lower|__ctype_print, /* g-z */ + __ctype_lower|__ctype_print, /* g-z */ + __ctype_lower|__ctype_print, /* g-z */ + __ctype_lower|__ctype_print, /* g-z */ + __ctype_lower|__ctype_print, /* g-z */ + __ctype_lower|__ctype_print, /* g-z */ + __ctype_lower|__ctype_print, /* g-z */ + __ctype_lower|__ctype_print, /* g-z */ + __ctype_lower|__ctype_print, /* g-z */ + __ctype_lower|__ctype_print, /* g-z */ + __ctype_lower|__ctype_print, /* g-z */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + 0, /* control character */ + + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + 0, /* control character */ + + __ctype_space|__ctype_print, /* NBSP */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_print|__ctype_punct, /* punctuation */ + + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_upper|__ctype_print, /* upper accented */ + + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_upper|__ctype_print, /* upper accented */ + __ctype_lower|__ctype_print, /* lower accented */ + + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_lower|__ctype_print, /* lower accented */ + + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_print|__ctype_punct, /* punctuation */ + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_lower|__ctype_print, /* lower accented */ + __ctype_lower|__ctype_print, /* lower accented */ +}; diff --git a/klibc/klibc/exec_l.c b/klibc/klibc/exec_l.c new file mode 100644 index 0000000000..cdae11e981 --- /dev/null +++ b/klibc/klibc/exec_l.c @@ -0,0 +1,57 @@ +/* + * exec_l.c + * + * Common implementation of execl() execle() execlp() + */ + +#include <stdarg.h> +#include <alloca.h> +#include <unistd.h> + +int NAME (const char *path, const char *arg0, ...) +{ + va_list ap, cap; + int argc = 1, rv; + const char **argv, **argp; + const char *arg; +#if EXEC_E + char * const * envp; +#else +#define envp environ +#endif + + va_start(ap, arg0); + va_copy(cap, ap); + + /* Count the number of arguments */ + do { + arg = va_arg(cap, const char *); + argc++; + } while ( arg ); + + va_end(cap); + + /* Allocate memory for the pointer array */ + argp = argv = alloca(argc*sizeof(const char *)); + if ( !argv ) { + va_end(ap); + return -1; + } + + /* Copy the list into an array */ + *argp++ = arg0; + do { + *argp++ = arg = va_arg(ap, const char *); + } while ( arg ); + +#if EXEC_E + /* execle() takes one more argument for the environment pointer */ + envp = va_arg(ap, char * const *); +#endif + + rv = (EXEC_P ? execvpe : execve)(path, (char * const *)argv, envp); + + va_end(ap); + + return rv; +} diff --git a/klibc/klibc/execl.c b/klibc/klibc/execl.c new file mode 100644 index 0000000000..4581113ba5 --- /dev/null +++ b/klibc/klibc/execl.c @@ -0,0 +1,8 @@ +/* + * execl.c + */ + +#define NAME execl +#define EXEC_P 0 +#define EXEC_E 0 +#include "exec_l.c" diff --git a/klibc/klibc/execle.c b/klibc/klibc/execle.c new file mode 100644 index 0000000000..b073988835 --- /dev/null +++ b/klibc/klibc/execle.c @@ -0,0 +1,8 @@ +/* + * execle.c + */ + +#define NAME execle +#define EXEC_P 0 +#define EXEC_E 1 +#include "exec_l.c" diff --git a/klibc/klibc/execlp.c b/klibc/klibc/execlp.c new file mode 100644 index 0000000000..65c9aa4a7a --- /dev/null +++ b/klibc/klibc/execlp.c @@ -0,0 +1,8 @@ +/* + * execlp.c + */ + +#define NAME execlp +#define EXEC_P 1 +#define EXEC_E 0 +#include "exec_l.c" diff --git a/klibc/klibc/execlpe.c b/klibc/klibc/execlpe.c new file mode 100644 index 0000000000..fef972fcb3 --- /dev/null +++ b/klibc/klibc/execlpe.c @@ -0,0 +1,8 @@ +/* + * execlpe.c + */ + +#define NAME execlpe +#define EXEC_P 1 +#define EXEC_E 1 +#include "exec_l.c" diff --git a/klibc/klibc/execv.c b/klibc/klibc/execv.c new file mode 100644 index 0000000000..9856b76d87 --- /dev/null +++ b/klibc/klibc/execv.c @@ -0,0 +1,13 @@ +/* + * execv.c + */ + +#include <stdarg.h> +#include <unistd.h> + +int execv(const char *path, char * const * argv) +{ + return execve(path, argv, environ); +} + + diff --git a/klibc/klibc/execvp.c b/klibc/klibc/execvp.c new file mode 100644 index 0000000000..b1065ee47e --- /dev/null +++ b/klibc/klibc/execvp.c @@ -0,0 +1,13 @@ +/* + * execvp.c + */ + +#include <stdarg.h> +#include <unistd.h> + +int execvp(const char *path, char * const * argv) +{ + return execvpe(path, argv, environ); +} + + diff --git a/klibc/klibc/execvpe.c b/klibc/klibc/execvpe.c new file mode 100644 index 0000000000..afd791ab43 --- /dev/null +++ b/klibc/klibc/execvpe.c @@ -0,0 +1,73 @@ +/* + * execvpe.c + * + * execvpe() function (from which we build execlp, execlpe, execvp). + * + * This version of execvpe() will *not* spawn /bin/sh if the command + * return ENOEXEC. That's what #! is for, folks! + * + * Since execlpe() and execvpe() aren't in POSIX, nor in glibc, + * I have followed QNX precedent in the implementation of the PATH: + * the PATH that is used is the one in the current environment, not + * in the new environment. + */ + +#include <errno.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> + +#define DEFAULT_PATH "/bin:/usr/bin:." + +int execvpe(const char *file, char * const *argv, char * const *envp) +{ + char path[PATH_MAX]; + const char *searchpath, *esp; + size_t prefixlen, filelen, totallen; + + if ( strchr(file, '/') ) /* Specific path */ + return execve(file, argv, envp); + + filelen = strlen(file); + + searchpath = getenv("PATH"); + if ( !searchpath ) + searchpath = DEFAULT_PATH; + + errno = ENOENT; /* Default errno, if execve() doesn't change it */ + + do { + esp = strchr(searchpath, ':'); + if ( esp ) + prefixlen = esp-searchpath; + else + prefixlen = strlen(searchpath); + + if ( prefixlen == 0 || searchpath[prefixlen-1] == '/' ) { + totallen = prefixlen+filelen; + if ( totallen >= PATH_MAX ) + continue; + memcpy(path, searchpath, prefixlen); + memcpy(path+prefixlen, file, filelen); + } else { + totallen = prefixlen+filelen+1; + if ( totallen >= PATH_MAX ) + continue; + memcpy(path, searchpath, prefixlen); + path[prefixlen] = '/'; + memcpy(path+prefixlen+1, file, filelen); + } + path[totallen] = '\0'; + + execve(path, argv, envp); + if ( errno == E2BIG || errno == ENOEXEC || + errno == ENOMEM || errno == ETXTBSY ) + break; /* Report this as an error, no more search */ + + searchpath = esp+1; + } while ( esp ); + + return -1; +} + diff --git a/klibc/klibc/exitc.c b/klibc/klibc/exitc.c new file mode 100644 index 0000000000..6e5d78979d --- /dev/null +++ b/klibc/klibc/exitc.c @@ -0,0 +1,36 @@ +/* + * exit.c + * + * Note: all programs need exit(), since it's invoked from + * crt0.o. Therefore there is no point in breaking apart + * exit() and _exit(). + */ + +#include <stdlib.h> +#include <unistd.h> +#include <sys/syscall.h> + +/* We have an assembly version for i386 and x86-64 */ + +#if !defined(__i386__) && !defined(__x86_64__) + +#define __NR___exit __NR_exit + +/* Syscalls can't return void... */ +static inline _syscall1(int,__exit,int,rv); + +/* This allows atexit/on_exit to install a hook */ +__noreturn (*__exit_handler)(int) = _exit; + +__noreturn exit(int rv) +{ + __exit_handler(rv); +} + +__noreturn _exit(int rv) +{ + __exit(rv); + for(;;); +} + +#endif diff --git a/klibc/klibc/fdatasync.c b/klibc/klibc/fdatasync.c new file mode 100644 index 0000000000..53079b09d6 --- /dev/null +++ b/klibc/klibc/fdatasync.c @@ -0,0 +1,15 @@ +/* + * fdatasync.c + * + * Some systems don't have this (alpha?) ... this is really a bug, + * but mimic using fsync() + */ + +#include <unistd.h> +#include <sys/syscall.h> + +#ifndef __NR_fdatasync +#define __NR_fdatasync __NR_fsync +#endif + +_syscall1(int,fdatasync,int,fd); diff --git a/klibc/klibc/fgetc.c b/klibc/klibc/fgetc.c new file mode 100644 index 0000000000..83eee16f61 --- /dev/null +++ b/klibc/klibc/fgetc.c @@ -0,0 +1,20 @@ +/* + * fgetc.c + * + * Extremely slow fgetc implementation, using _fread(). If people + * actually need character-oriented input to be fast, we may actually + * have to implement buffering. Sigh. + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <errno.h> + +int fgetc(FILE *f) +{ + unsigned char ch; + + return (_fread(&ch, 1, f) == 1) ? (int)ch : EOF; +} + diff --git a/klibc/klibc/fgets.c b/klibc/klibc/fgets.c new file mode 100644 index 0000000000..88a145a63f --- /dev/null +++ b/klibc/klibc/fgets.c @@ -0,0 +1,33 @@ +/* + * fgets.c + * + * This will be very slow due to the implementation of getc(), + * but we can't afford to drain characters we don't need from + * the input. + */ + +#include <stdio.h> + +char *fgets(char *s, int n, FILE *f) +{ + int ch; + char *p = s; + + while ( n > 1 ) { + ch = getc(f); + if ( ch == EOF ) { + *p = '\0'; + return NULL; + } + *p++ = ch; + if ( ch == '\n' ) + break; + } + if ( n ) + *p = '\0'; + + return s; +} + + + diff --git a/klibc/klibc/fopen.c b/klibc/klibc/fopen.c new file mode 100644 index 0000000000..5c84184809 --- /dev/null +++ b/klibc/klibc/fopen.c @@ -0,0 +1,46 @@ +/* + * fopen.c + */ + +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> + +/* This depends on O_RDONLY == 0, O_WRONLY == 1, O_RDWR == 2 */ + + +FILE *fopen(const char *file, const char *mode) +{ + int flags = O_RDONLY; + int plus = 0; + int fd; + + while ( *mode ) { + switch ( *mode ) { + case 'r': + flags = O_RDONLY; + break; + case 'w': + flags = O_WRONLY|O_CREAT|O_TRUNC; + break; + case 'a': + flags = O_WRONLY|O_CREAT|O_APPEND; + break; + case '+': + plus = 1; + break; + } + mode++; + } + + if ( plus ) { + flags = (flags & ~(O_RDONLY|O_WRONLY)) | O_RDWR; + } + + fd = open(file, flags, 0666); + + if ( fd < 0 ) + return NULL; + else + return fdopen(fd, mode); +} diff --git a/klibc/klibc/fork.c b/klibc/klibc/fork.c new file mode 100644 index 0000000000..d7e4db89a1 --- /dev/null +++ b/klibc/klibc/fork.c @@ -0,0 +1,29 @@ +/* + * fork.c + * + * This is normally just a syscall stub, but at least one system + * doesn't have sys_fork, only sys_clone... + */ + +#include <sys/syscall.h> +#include <signal.h> +#include <unistd.h> + +#ifdef __NR_fork + +#ifdef _syscall0_forkish +_syscall0_forkish(pid_t,fork); +#else +_syscall0(pid_t,fork); +#endif + +#else /* __NR_fork */ + +static inline _syscall2(pid_t,clone,unsigned long,flags,void *,newsp); + +pid_t fork(void) +{ + return clone(SIGCHLD, 0); +} + +#endif /* __NR_fork */ diff --git a/klibc/klibc/fprintf.c b/klibc/klibc/fprintf.c new file mode 100644 index 0000000000..df3823eac3 --- /dev/null +++ b/klibc/klibc/fprintf.c @@ -0,0 +1,19 @@ +/* + * fprintf.c + */ + +#include <stdio.h> +#include <stdarg.h> + +#define BUFFER_SIZE 16384 + +int fprintf(FILE *file, const char *format, ...) +{ + va_list ap; + int rv; + + va_start(ap, format); + rv = vfprintf(file, format, ap); + va_end(ap); + return rv; +} diff --git a/klibc/klibc/fputc.c b/klibc/klibc/fputc.c new file mode 100644 index 0000000000..61aff1644b --- /dev/null +++ b/klibc/klibc/fputc.c @@ -0,0 +1,14 @@ +/* + * fputc.c + * + * gcc "printf decompilation" expects this to exist... + */ + +#include <stdio.h> + +int fputc(int c, FILE *f) +{ + unsigned char ch = c; + + return _fwrite(&ch, 1, f) == 1 ? ch : EOF; +} diff --git a/klibc/klibc/fputs.c b/klibc/klibc/fputs.c new file mode 100644 index 0000000000..4b68f96886 --- /dev/null +++ b/klibc/klibc/fputs.c @@ -0,0 +1,15 @@ +/* + * fputs.c + * + * This isn't quite fputs() in the stdio sense, since we don't + * have stdio, but it takes a file descriptor argument instead + * of the FILE *. + */ + +#include <stdio.h> +#include <string.h> + +int fputs(const char *s, FILE *file) +{ + return _fwrite(s, strlen(s), file); +} diff --git a/klibc/klibc/fread.c b/klibc/klibc/fread.c new file mode 100644 index 0000000000..8f7dba9c19 --- /dev/null +++ b/klibc/klibc/fread.c @@ -0,0 +1,35 @@ +/* + * fread.c + */ + +#include <errno.h> +#include <unistd.h> +#include <stdio.h> + +size_t _fread(void *buf, size_t count, FILE *f) +{ + size_t bytes = 0; + ssize_t rv; + char *p = buf; + + while ( count ) { + rv = read(fileno(f), p, count); + if ( rv == -1 ) { + if ( errno == EINTR ) + continue; + else + break; + } else if ( rv == 0 ) { + break; + } + + p += rv; + bytes += rv; + count -= rv; + } + + return bytes; +} + + + diff --git a/klibc/klibc/fread2.c b/klibc/klibc/fread2.c new file mode 100644 index 0000000000..9e5ac81fc2 --- /dev/null +++ b/klibc/klibc/fread2.c @@ -0,0 +1,13 @@ +/* + * fread2.c + * + * The actual fread() function as a non-inline + */ + +#define __NO_FREAD_FWRITE_INLINES +#include <stdio.h> + +size_t fread(void *ptr, size_t size, size_t nmemb, FILE *f) +{ + return _fread(ptr, size*nmemb, f)/size; +} diff --git a/klibc/klibc/fwrite.c b/klibc/klibc/fwrite.c new file mode 100644 index 0000000000..0a73188c67 --- /dev/null +++ b/klibc/klibc/fwrite.c @@ -0,0 +1,35 @@ +/* + * fwrite.c + */ + +#include <errno.h> +#include <unistd.h> +#include <stdio.h> + +size_t _fwrite(const void *buf, size_t count, FILE *f) +{ + size_t bytes = 0; + ssize_t rv; + const char *p = buf; + + while ( count ) { + rv = write(fileno(f), p, count); + if ( rv == -1 ) { + if ( errno == EINTR ) + continue; + else + break; + } else if ( rv == 0 ) { + break; + } + + p += rv; + bytes += rv; + count -= rv; + } + + return bytes; +} + + + diff --git a/klibc/klibc/fwrite2.c b/klibc/klibc/fwrite2.c new file mode 100644 index 0000000000..82ec832be4 --- /dev/null +++ b/klibc/klibc/fwrite2.c @@ -0,0 +1,13 @@ +/* + * fwrite2.c + * + * The actual fwrite() function as a non-inline + */ + +#define __NO_FREAD_FWRITE_INLINES +#include <stdio.h> + +size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *f) +{ + return _fwrite(ptr, size*nmemb, f)/size; +} diff --git a/klibc/klibc/getcwd.c b/klibc/klibc/getcwd.c new file mode 100644 index 0000000000..350ec69a63 --- /dev/null +++ b/klibc/klibc/getcwd.c @@ -0,0 +1,15 @@ +/* + * getcwd.c + */ + +#include <unistd.h> +#include <sys/syscall.h> + +#define __NR___getcwd __NR_getcwd +static inline _syscall2(int,__getcwd,char *,buf,size_t,size); + +char *getcwd(char *buf, size_t size) +{ + return ( __getcwd(buf, size) < 0 ) ? NULL : buf; +} + diff --git a/klibc/klibc/getdomainname.c b/klibc/klibc/getdomainname.c new file mode 100644 index 0000000000..4cd68a3cb5 --- /dev/null +++ b/klibc/klibc/getdomainname.c @@ -0,0 +1,25 @@ +/* + * getdomainname.c + */ + +#include <errno.h> +#include <unistd.h> +#include <string.h> +#include <sys/utsname.h> + +int getdomainname(char *name, size_t len) +{ + struct utsname un; + + if ( !uname(&un) ) + return -1; + + if ( len < strlen(un.domainname)+1 ) { + errno = EINVAL; + return -1; + } + + strcpy(name, un.domainname); + + return 0; +} diff --git a/klibc/klibc/getenv.c b/klibc/klibc/getenv.c new file mode 100644 index 0000000000..84fc94c00e --- /dev/null +++ b/klibc/klibc/getenv.c @@ -0,0 +1,22 @@ +/* + * getenv.c + */ + +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +char *getenv(const char *name) +{ + char **p, *q; + int len = strlen(name); + + for ( p = environ ; (q = *p) ; p++ ) { + if ( !strncmp(name, q, len) && q[len] == '=' ) { + return q+(len+1); + } + } + + return NULL; +} + diff --git a/klibc/klibc/gethostname.c b/klibc/klibc/gethostname.c new file mode 100644 index 0000000000..6c5062e816 --- /dev/null +++ b/klibc/klibc/gethostname.c @@ -0,0 +1,25 @@ +/* + * gethostname.c + */ + +#include <errno.h> +#include <unistd.h> +#include <string.h> +#include <sys/utsname.h> + +int gethostname(char *name, size_t len) +{ + struct utsname un; + + if ( !uname(&un) ) + return -1; + + if ( len < strlen(un.nodename)+1 ) { + errno = EINVAL; + return -1; + } + + strcpy(name, un.nodename); + + return 0; +} diff --git a/klibc/klibc/getopt.c b/klibc/klibc/getopt.c new file mode 100644 index 0000000000..5a992dcdd7 --- /dev/null +++ b/klibc/klibc/getopt.c @@ -0,0 +1,74 @@ +/* + * getopt.c + * + * Simple POSIX getopt(), no GNU extensions... + */ + +#include <stdint.h> +#include <unistd.h> +#include <string.h> + +char *optarg; +int optind = 1; +int opterr, optopt; +static const char *__optptr; + +int getopt(int argc, char * const *argv, const char *optstring) +{ + const char *carg = argv[optind]; + const char *osptr; + int opt; + + /* We don't actually need argc */ + (void)argc; + + /* First, eliminate all non-option cases */ + + if ( !carg || carg[0] != '-' || !carg[1] ) { + return -1; + } + + if ( carg[1] == '-' && !carg[2] ) { + optind++; + return -1; + } + + if ( (uintptr_t)(__optptr-carg) > (uintptr_t)strlen(carg) ) + __optptr = carg+1; /* Someone frobbed optind, change to new opt. */ + + opt = *__optptr++; + + if ( opt != ':' && (osptr = strchr(optstring, opt)) ) { + if ( osptr[1] == ':' ) { + if ( *__optptr ) { + /* Argument-taking option with attached argument */ + optarg = (char *)__optptr; + optind++; + } else { + /* Argument-taking option with non-attached argument */ + if ( argv[optind+1] ) { + optarg = (char *)argv[optind+1]; + optind += 2; + } else { + /* Missing argument */ + return (optstring[0] == ':') ? ':' : '?'; + } + } + return opt; + } else { + /* Non-argument-taking option */ + /* __optptr will remember the exact position to resume at */ + if ( ! *__optptr ) + optind++; + return opt; + } + } else { + /* Unknown option */ + optopt = opt; + if ( ! *__optptr ) + optind++; + return '?'; + } +} + + diff --git a/klibc/klibc/getpriority.c b/klibc/klibc/getpriority.c new file mode 100644 index 0000000000..d6db2cc6b9 --- /dev/null +++ b/klibc/klibc/getpriority.c @@ -0,0 +1,25 @@ +/* + * getpriority.c + * + * Needs to do some post-syscall mangling to distinguish error returns... + * but only on some platforms. Sigh. + */ + +#include <unistd.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <sys/syscall.h> + +#define __NR__getpriority __NR_getpriority + +static inline _syscall2(int,_getpriority,int,which,int,who); + +int getpriority(int which, int who) +{ +#if defined(__alpha__) || defined(__ia64__) + return _getpriority(which, who); +#else + int rv = _getpriority(which, who); + return ( rv < 0 ) ? rv : 20-rv; +#endif +} diff --git a/klibc/klibc/globals.c b/klibc/klibc/globals.c new file mode 100644 index 0000000000..72ae91fbad --- /dev/null +++ b/klibc/klibc/globals.c @@ -0,0 +1,10 @@ +/* + * globals.c + * + * These have to be defined somewhere... + */ +#include <errno.h> +#include <unistd.h> + +int errno; +char **environ; diff --git a/klibc/klibc/include/alloca.h b/klibc/klibc/include/alloca.h new file mode 100644 index 0000000000..41a4d94d44 --- /dev/null +++ b/klibc/klibc/include/alloca.h @@ -0,0 +1,13 @@ +/* + * alloca.h + * + * Just call the builtin alloca() function + */ + +#ifndef _ALLOCA_H +#define _ALLOCA_H + +#define alloca(size) __builtin_alloca(size) + +#endif /* _ALLOCA_H */ + diff --git a/klibc/klibc/include/arpa/inet.h b/klibc/klibc/include/arpa/inet.h new file mode 100644 index 0000000000..043b148e17 --- /dev/null +++ b/klibc/klibc/include/arpa/inet.h @@ -0,0 +1,24 @@ +/* + * arpa/inet.h + */ + +#ifndef _ARPA_INET_H +#define _ARPA_INET_H + +#include <klibc/extern.h> +#include <stdint.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <netinet/in6.h> + +__extern uint32_t inet_addr(const char *); +__extern int inet_aton(const char *, struct in_addr *); +__extern char *inet_ntoa(struct in_addr); +__extern int inet_pton(int, const char *, void *); +__extern const char *inet_ntop(int, const void *, char *, size_t); +__extern unsigned int inet_nsap_addr(const char *, unsigned char *, int); +__extern char *inet_nsap_ntoa(int, const unsigned char *, char *); + +#endif /* _ARPA_INET_H */ + + diff --git a/klibc/klibc/include/assert.h b/klibc/klibc/include/assert.h new file mode 100644 index 0000000000..58cc37c487 --- /dev/null +++ b/klibc/klibc/include/assert.h @@ -0,0 +1,22 @@ +/* + * assert.h + */ + +#ifndef _ASSERT_H +#define _ASSERT_H + +#ifdef NDEBUG + +#define assert(x) ((void)(x)) + +#else + +extern void __assert_fail(const char *, const char *, + unsigned int); + +#define assert(x) ((x) ? (void)0 : __assert_fail(#x, __FILE__, __LINE__)) + +#endif + +#endif /* _ASSERT_H */ + diff --git a/klibc/klibc/include/bits32/bitsize/limits.h b/klibc/klibc/include/bits32/bitsize/limits.h new file mode 100644 index 0000000000..f90e524b2b --- /dev/null +++ b/klibc/klibc/include/bits32/bitsize/limits.h @@ -0,0 +1,14 @@ +/* + * bits32/limits.h + */ + +#ifndef _BITSIZE_LIMITS_H +#define _BITSIZE_LIMITS_H + +#define LONG_BIT 32 + +#define LONG_MIN (-2147483647L-1) +#define LONG_MAX 2147483647L +#define ULONG_MAX 4294967295UL + +#endif /* _BITSIZE_LIMITS_H */ diff --git a/klibc/klibc/include/bits32/bitsize/stddef.h b/klibc/klibc/include/bits32/bitsize/stddef.h new file mode 100644 index 0000000000..bf6e695ed3 --- /dev/null +++ b/klibc/klibc/include/bits32/bitsize/stddef.h @@ -0,0 +1,18 @@ +/* + * bits32/stddef.h + */ + +#ifndef _BITSIZE_STDDEF_H +#define _BITSIZE_STDDEF_H + +#define _SIZE_T +#if (defined(__s390__) || defined(__hppa__) || defined(__cris__)) +typedef unsigned long size_t; +#else +typedef unsigned int size_t; +#endif + +#define _PTRDIFF_T +typedef signed int ptrdiff_t; + +#endif /* _BITSIZE_STDDEF_H */ diff --git a/klibc/klibc/include/bits32/bitsize/stdint.h b/klibc/klibc/include/bits32/bitsize/stdint.h new file mode 100644 index 0000000000..40b464961c --- /dev/null +++ b/klibc/klibc/include/bits32/bitsize/stdint.h @@ -0,0 +1,34 @@ +/* + * bits32/stdint.h + */ + +#ifndef _BITSIZE_STDINT_H +#define _BITSIZE_STDINT_H + +typedef signed char int8_t; +typedef short int int16_t; +typedef int int32_t; +typedef long long int int64_t; + +typedef unsigned char uint8_t; +typedef unsigned short int uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long int uint64_t; + +typedef int int_fast16_t; +typedef int int_fast32_t; + +typedef unsigned int uint_fast16_t; +typedef unsigned int uint_fast32_t; + +typedef int intptr_t; +typedef unsigned int uintptr_t; + +#define __INT64_C(c) c ## LL +#define __UINT64_C(c) c ## ULL + +#define __PRI64_RANK "ll" +#define __PRIFAST_RANK "" +#define __PRIPTR_RANK "" + +#endif /* _BITSIZE_STDINT_H */ diff --git a/klibc/klibc/include/bits32/bitsize/stdintconst.h b/klibc/klibc/include/bits32/bitsize/stdintconst.h new file mode 100644 index 0000000000..8157dd06e0 --- /dev/null +++ b/klibc/klibc/include/bits32/bitsize/stdintconst.h @@ -0,0 +1,18 @@ +/* + * bits32/stdintconst.h + */ + +#ifndef _BITSIZE_STDINTCONST_H +#define _BITSIZE_STDINTCONST_H + +#define INT_FAST16_C(c) INT32_C(c) +#define INT_FAST32_C(c) INT32_C(c) + +#define UINT_FAST16_C(c) UINT32_C(c) +#define UINT_FAST32_C(c) UINT32_C(c) + +#define INTPTR_C(c) INT32_C(c) +#define UINTPTR_C(c) UINT32_C(c) +#define PTRDIFF_C(c) INT32_C(c) + +#endif /* _BITSIZE_STDINTCONST_H */ diff --git a/klibc/klibc/include/bits32/bitsize/stdintlimits.h b/klibc/klibc/include/bits32/bitsize/stdintlimits.h new file mode 100644 index 0000000000..b44fe01186 --- /dev/null +++ b/klibc/klibc/include/bits32/bitsize/stdintlimits.h @@ -0,0 +1,22 @@ +/* + * bits32/stdintlimits.h + */ + +#ifndef _BITSIZE_STDINTLIMITS_H +#define _BITSIZE_STDINTLIMITS_H + +#define INT_FAST16_MIN INT32_MIN +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST16_MAX INT32_MAX +#define INT_FAST32_MAX INT32_MAX +#define UINT_FAST16_MAX UINT32_MAX +#define UINT_FAST32_MAX UINT32_MAX + +#define INTPTR_MIN INT32_MIN +#define INTPTR_MAX INT32_MAX +#define UINTPTR_MAX UINT32_MAX + +#define PTRDIFF_MIN INT32_MIN +#define PTRDIFF_MAX INT32_MAX + +#endif /* _BITSIZE_STDINTLIMITS_H */ diff --git a/klibc/klibc/include/bits64/bitsize/limits.h b/klibc/klibc/include/bits64/bitsize/limits.h new file mode 100644 index 0000000000..7b20da085b --- /dev/null +++ b/klibc/klibc/include/bits64/bitsize/limits.h @@ -0,0 +1,14 @@ +/* + * bits64/limits.h + */ + +#ifndef _BITSIZE_LIMITS_H +#define _BITSIZE_LIMITS_H + +#define LONG_BIT 64 + +#define LONG_MIN (-9223372036854775807L-1) +#define LONG_MAX 9223372036854775807L +#define ULONG_MAX 18446744073709551615UL + +#endif /* _BITSIZE_LIMITS_H */ diff --git a/klibc/klibc/include/bits64/bitsize/stddef.h b/klibc/klibc/include/bits64/bitsize/stddef.h new file mode 100644 index 0000000000..3e72621862 --- /dev/null +++ b/klibc/klibc/include/bits64/bitsize/stddef.h @@ -0,0 +1,13 @@ +/* + * bits64/stddef.h + */ + +#ifndef _BITSIZE_STDDEF_H +#define _BITSIZE_STDDEF_H + +#define _SIZE_T +typedef unsigned long size_t; +#define _PTRDIFF_T +typedef signed long ptrdiff_t; + +#endif /* _BITSIZE_STDDEF_H */ diff --git a/klibc/klibc/include/bits64/bitsize/stdint.h b/klibc/klibc/include/bits64/bitsize/stdint.h new file mode 100644 index 0000000000..f569f526b6 --- /dev/null +++ b/klibc/klibc/include/bits64/bitsize/stdint.h @@ -0,0 +1,36 @@ +/* + * bits64/stdint.h + */ + +#ifndef _BITSIZE_STDINT_H +#define _BITSIZE_STDINT_H + +typedef signed char int8_t; +typedef short int int16_t; +typedef int int32_t; +typedef long long int int64_t; + +typedef unsigned char uint8_t; +typedef unsigned short int uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long int uint64_t; + +typedef long int int_fast16_t; +typedef long int int_fast32_t; + +typedef unsigned long int uint_fast16_t; +typedef unsigned long int uint_fast32_t; + +typedef long int intptr_t; +typedef unsigned long int uintptr_t; + +#define __INT64_C(c) c ## L +#define __UINT64_C(c) c ## UL + +#define __PRI64_RANK "l" +#define __PRIFAST_RANK "l" +#define __PRIPTR_RANK "l" + +#endif /* _BITSIZE_STDINT_H */ + + diff --git a/klibc/klibc/include/bits64/bitsize/stdintconst.h b/klibc/klibc/include/bits64/bitsize/stdintconst.h new file mode 100644 index 0000000000..65f2db0501 --- /dev/null +++ b/klibc/klibc/include/bits64/bitsize/stdintconst.h @@ -0,0 +1,18 @@ +/* + * bits64/stdintconst.h + */ + +#ifndef _BITSIZE_STDINTCONST_H +#define _BITSIZE_STDINTCONST_H + +#define INT_FAST16_C(c) INT64_C(c) +#define INT_FAST32_C(c) INT64_C(c) + +#define UINT_FAST16_C(c) UINT64_C(c) +#define UINT_FAST32_C(c) UINT64_C(c) + +#define INTPTR_C(c) INT64_C(c) +#define UINTPTR_C(c) UINT64_C(c) +#define PTRDIFF_C(c) INT64_C(c) + +#endif /* _BITSIZE_STDINTCONST_H */ diff --git a/klibc/klibc/include/bits64/bitsize/stdintlimits.h b/klibc/klibc/include/bits64/bitsize/stdintlimits.h new file mode 100644 index 0000000000..d110d17d2d --- /dev/null +++ b/klibc/klibc/include/bits64/bitsize/stdintlimits.h @@ -0,0 +1,22 @@ +/* + * bits64/stdintlimits.h + */ + +#ifndef _BITSIZE_STDINTLIMITS_H +#define _BITSIZE_STDINTLIMITS_H + +#define INT_FAST16_MIN INT64_MIN +#define INT_FAST32_MIN INT64_MIN +#define INT_FAST16_MAX INT64_MAX +#define INT_FAST32_MAX INT64_MAX +#define UINT_FAST16_MAX UINT64_MAX +#define UINT_FAST32_MAX UINT64_MAX + +#define INTPTR_MIN INT64_MIN +#define INTPTR_MAX INT64_MAX +#define UINTPTR_MAX UINT64_MAX + +#define PTRDIFF_MIN INT64_MIN +#define PTRDIFF_MAX INT64_MAX + +#endif /* _BITSIZE_STDINTLIMITS_H */ diff --git a/klibc/klibc/include/ctype.h b/klibc/klibc/include/ctype.h new file mode 100644 index 0000000000..2cb90a45d3 --- /dev/null +++ b/klibc/klibc/include/ctype.h @@ -0,0 +1,117 @@ +/* + * ctype.h + * + * This assumes ISO 8859-1, being a reasonable superset of ASCII. + */ + +#ifndef _CTYPE_H +#define _CTYPE_H + +#ifndef __CTYPE_NO_INLINE +# define __ctype_inline extern __inline__ +#else +# define __ctype_inline +#endif + +/* + * This relies on the following definitions: + * + * cntrl = !print + * alpha = upper|lower + * graph = punct|alpha|digit + * blank = '\t' || ' ' (per POSIX requirement) + */ +enum { + __ctype_upper = (1 << 0), + __ctype_lower = (1 << 1), + __ctype_digit = (1 << 2), + __ctype_xdigit = (1 << 3), + __ctype_space = (1 << 4), + __ctype_print = (1 << 5), + __ctype_punct = (1 << 6) +}; + +extern const unsigned char __ctypes[]; + +__ctype_inline int isalnum(int __c) +{ + return __ctypes[__c+1] & + (__ctype_upper|__ctype_lower|__ctype_digit); +} + +__ctype_inline int isalpha(int __c) +{ + return __ctypes[__c+1] & + (__ctype_upper|__ctype_lower); +} + +__ctype_inline int isascii(int __c) +{ + return !(__c & ~0x7f); +} + +__ctype_inline int isblank(int __c) +{ + return (__c == '\t') || (__c == ' '); +} + +__ctype_inline int iscntrl(int __c) +{ + return (__c >= 0) && !(__ctypes[__c+1] & __ctype_print); +} + +__ctype_inline int isdigit(int __c) +{ + return __ctypes[__c+1] & __ctype_digit; +} + +__ctype_inline int isgraph(int __c) +{ + return __ctypes[__c+1] & + (__ctype_upper|__ctype_lower|__ctype_digit|__ctype_punct); +} + +__ctype_inline int islower(int __c) +{ + return __ctypes[__c+1] & __ctype_lower; +} + +__ctype_inline int isprint(int __c) +{ + return __ctypes[__c+1] & __ctype_print; +} + +__ctype_inline int ispunct(int __c) +{ + return __ctypes[__c+1] & __ctype_punct; +} + +__ctype_inline int isspace(int __c) +{ + return __ctypes[__c+1] & __ctype_space; +} + +__ctype_inline int isupper(int __c) +{ + return __ctypes[__c+1] & __ctype_upper; +} + +__ctype_inline int isxdigit(int __c) +{ + return __ctypes[__c+1] & __ctype_xdigit; +} + +#define _toupper(__c) ((__c) & ~0x20) +#define _tolower(__c) ((__c) | 0x20) + +__ctype_inline int toupper(int __c) +{ + return islower(__c) ? _toupper(__c) : __c; +} + +__ctype_inline int tolower(int __c) +{ + return isupper(__c) ? _tolower(__c) : __c; +} + +#endif /* _CTYPE_H */ diff --git a/klibc/klibc/include/dirent.h b/klibc/klibc/include/dirent.h new file mode 100644 index 0000000000..10dd138ee5 --- /dev/null +++ b/klibc/klibc/include/dirent.h @@ -0,0 +1,20 @@ +/* + * dirent.h + */ + +#ifndef _DIRENT_H +#define _DIRENT_H + +#include <klibc/extern.h> +#include <sys/dirent.h> + +#ifndef __IO_DIR_DEFINED +struct _IO_dir; +#endif +typedef struct _IO_dir DIR; + +__extern DIR *opendir(const char *); +__extern struct dirent *readdir(DIR *); +__extern int closedir(DIR *); + +#endif /* _DIRENT_H */ diff --git a/klibc/klibc/include/elf.h b/klibc/klibc/include/elf.h new file mode 100644 index 0000000000..bd0f3e7f9b --- /dev/null +++ b/klibc/klibc/include/elf.h @@ -0,0 +1,12 @@ +/* + * elf.h + */ + +#ifndef _ELF_H +#define _ELF_H + +#include <sys/types.h> +#include <linux/elf.h> + +#endif /* _ELF_H */ + diff --git a/klibc/klibc/include/endian.h b/klibc/klibc/include/endian.h new file mode 100644 index 0000000000..10dbbd8a89 --- /dev/null +++ b/klibc/klibc/include/endian.h @@ -0,0 +1,41 @@ +/* + * endian.h + */ + +#ifndef _ENDIAN_H +#define _ENDIAN_H + +#include <asm/byteorder.h> + +/* Linux' asm/byteorder.h defines either __LITTLE_ENDIAN or + __BIG_ENDIAN, but the glibc/BSD-ish macros expect both to be + defined with __BYTE_ORDER defining which is actually used... */ + +#if defined(__LITTLE_ENDIAN) +# undef __LITTLE_ENDIAN +# define __LITTLE_ENDIAN 1234 +# define __BIG_ENDIAN 4321 +# define __PDP_ENDIAN 3412 +# define __BYTE_ORDER __LITTLE_ENDIAN +#elif defined(__BIG_ENDIAN) +# undef __BIG_ENDIAN +# define __LITTLE_ENDIAN 1234 +# define __BIG_ENDIAN 4321 +# define __PDP_ENDIAN 3412 +# define __BYTE_ORDER __BIG_ENDIAN +#elif defined(__PDP_ENDIAN) +# undef __PDP_ENDIAN +# define __LITTLE_ENDIAN 1234 +# define __BIG_ENDIAN 4321 +# define __PDP_ENDIAN 3412 +# define __BYTE_ORDER __PDP_ENDIAN +#else +# error "Unknown byte order!" +#endif + +#define LITTLE_ENDIAN __LITTLE_ENDIAN +#define BIG_ENDIAN __BIG_ENDIAN +#define PDP_ENDIAN __PDP_ENDIAN +#define BYTE_ORDER __BYTE_ORDER + +#endif /* _ENDIAN_H */ diff --git a/klibc/klibc/include/errno.h b/klibc/klibc/include/errno.h new file mode 100644 index 0000000000..b2e666504d --- /dev/null +++ b/klibc/klibc/include/errno.h @@ -0,0 +1,8 @@ +/* + * errno.h + */ + +#include <klibc/extern.h> +#include <asm/errno.h> + +__extern int errno; diff --git a/klibc/klibc/include/fcntl.h b/klibc/klibc/include/fcntl.h new file mode 100644 index 0000000000..e90959c7e9 --- /dev/null +++ b/klibc/klibc/include/fcntl.h @@ -0,0 +1,11 @@ +/* + * fcntl.h + */ + +#ifndef _FCNTL_H +#define _FCNTL_H + +#include <sys/types.h> +#include <linux/fcntl.h> + +#endif /* _FCNTL_H */ diff --git a/klibc/klibc/include/grp.h b/klibc/klibc/include/grp.h new file mode 100644 index 0000000000..03ceb31560 --- /dev/null +++ b/klibc/klibc/include/grp.h @@ -0,0 +1,13 @@ +/* + * grp.h + */ + +#ifndef _GRP_H +#define _GRP_H + +#include <klibc/extern.h> +#include <sys/types.h> + +__extern int setgroups(size_t, const gid_t *); + +#endif /* _GRP_H */ diff --git a/klibc/klibc/include/inttypes.h b/klibc/klibc/include/inttypes.h new file mode 100644 index 0000000000..e00fa63160 --- /dev/null +++ b/klibc/klibc/include/inttypes.h @@ -0,0 +1,226 @@ +/* + * inttypes.h + */ + +#ifndef _INTTYPES_H +#define _INTTYPES_H + +#include <klibc/extern.h> +#include <stdint.h> +#include <stddef.h> + +static __inline__ intmax_t imaxabs(intmax_t __n) +{ + return (__n < (intmax_t)0) ? -__n : __n; +} + +__extern intmax_t strtoimax(const char *, char **, int); +__extern uintmax_t strtoumax(const char *, char **, int); + +/* extensions */ +__extern intmax_t strntoimax(const char *, char **, int, size_t); +__extern uintmax_t strntoumax(const char *, char **, int, size_t); + +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) + +#define PRId8 "d" +#define PRId16 "d" +#define PRId32 "d" +#define PRId64 __PRI64_RANK "d" + +#define PRIdLEAST8 "d" +#define PRIdLEAST16 "d" +#define PRIdLEAST32 "d" +#define PRIdLEAST64 __PRI64_RANK "d" + +#define PRIdFAST8 "d" +#define PRIdFAST16 __PRIFAST_RANK "d" +#define PRIdFAST32 __PRIFAST_RANK "d" +#define PRIdFAST64 __PRI64_RANK "d" + +#define PRIdMAX __PRI64_RANK "d" +#define PRIdPTR __PRIPTR_RANK "d" + +#define PRIi8 "i" +#define PRIi16 "i" +#define PRIi32 "i" +#define PRIi64 __PRI64_RANK "i" + +#define PRIiLEAST8 "i" +#define PRIiLEAST16 "i" +#define PRIiLEAST32 "i" +#define PRIiLEAST64 __PRI64_RANK "i" + +#define PRIiFAST8 "i" +#define PRIiFAST16 __PRIFAST_RANK "i" +#define PRIiFAST32 __PRIFAST_RANK "i" +#define PRIiFAST64 __PRI64_RANK "i" + +#define PRIiMAX __PRI64_RANK "i" +#define PRIiPTR __PRIPTR_RANK "i" + +#define PRIo8 "o" +#define PRIo16 "o" +#define PRIo32 "o" +#define PRIo64 __PRI64_RANK "o" + +#define PRIoLEAST8 "o" +#define PRIoLEAST16 "o" +#define PRIoLEAST32 "o" +#define PRIoLEAST64 __PRI64_RANK "o" + +#define PRIoFAST8 "o" +#define PRIoFAST16 __PRIFAST_RANK "o" +#define PRIoFAST32 __PRIFAST_RANK "o" +#define PRIoFAST64 __PRI64_RANK "o" + +#define PRIoMAX __PRI64_RANK "o" +#define PRIoPTR __PRIPTR_RANK "o" + +#define PRIu8 "u" +#define PRIu16 "u" +#define PRIu32 "u" +#define PRIu64 __PRI64_RANK "u" + +#define PRIuLEAST8 "u" +#define PRIuLEAST16 "u" +#define PRIuLEAST32 "u" +#define PRIuLEAST64 __PRI64_RANK "u" + +#define PRIuFAST8 "u" +#define PRIuFAST16 __PRIFAST_RANK "u" +#define PRIuFAST32 __PRIFAST_RANK "u" +#define PRIuFAST64 __PRI64_RANK "u" + +#define PRIuMAX __PRI64_RANK "u" +#define PRIuPTR __PRIPTR_RANK "u" + +#define PRIx8 "x" +#define PRIx16 "x" +#define PRIx32 "x" +#define PRIx64 __PRI64_RANK "x" + +#define PRIxLEAST8 "x" +#define PRIxLEAST16 "x" +#define PRIxLEAST32 "x" +#define PRIxLEAST64 __PRI64_RANK "x" + +#define PRIxFAST8 "x" +#define PRIxFAST16 __PRIFAST_RANK "x" +#define PRIxFAST32 __PRIFAST_RANK "x" +#define PRIxFAST64 __PRI64_RANK "x" + +#define PRIxMAX __PRI64_RANK "x" +#define PRIxPTR __PRIPTR_RANK "x" + +#define PRIX8 "X" +#define PRIX16 "X" +#define PRIX32 "X" +#define PRIX64 __PRI64_RANK "X" + +#define PRIXLEAST8 "X" +#define PRIXLEAST16 "X" +#define PRIXLEAST32 "X" +#define PRIXLEAST64 __PRI64_RANK "X" + +#define PRIXFAST8 "X" +#define PRIXFAST16 __PRIFAST_RANK "X" +#define PRIXFAST32 __PRIFAST_RANK "X" +#define PRIXFAST64 __PRI64_RANK "X" + +#define PRIXMAX __PRI64_RANK "X" +#define PRIXPTR __PRIPTR_RANK "X" + +#define SCNd8 "hhd" +#define SCNd16 "hd" +#define SCNd32 "d" +#define SCNd64 __PRI64_RANK "d" + +#define SCNdLEAST8 "hhd" +#define SCNdLEAST16 "hd" +#define SCNdLEAST32 "d" +#define SCNdLEAST64 __PRI64_RANK "d" + +#define SCNdFAST8 "hhd" +#define SCNdFAST16 __PRIFAST_RANK "d" +#define SCNdFAST32 __PRIFAST_RANK "d" +#define SCNdFAST64 __PRI64_RANK "d" + +#define SCNdMAX __PRI64_RANK "d" +#define SCNdPTR __PRIPTR_RANK "d" + +#define SCNi8 "hhi" +#define SCNi16 "hi" +#define SCNi32 "i" +#define SCNi64 __PRI64_RANK "i" + +#define SCNiLEAST8 "hhi" +#define SCNiLEAST16 "hi" +#define SCNiLEAST32 "i" +#define SCNiLEAST64 __PRI64_RANK "i" + +#define SCNiFAST8 "hhi" +#define SCNiFAST16 __PRIFAST_RANK "i" +#define SCNiFAST32 __PRIFAST_RANK "i" +#define SCNiFAST64 __PRI64_RANK "i" + +#define SCNiMAX __PRI64_RANK "i" +#define SCNiPTR __PRIPTR_RANK "i" + +#define SCNo8 "hho" +#define SCNo16 "ho" +#define SCNo32 "o" +#define SCNo64 __PRI64_RANK "o" + +#define SCNoLEAST8 "hho" +#define SCNoLEAST16 "ho" +#define SCNoLEAST32 "o" +#define SCNoLEAST64 __PRI64_RANK "o" + +#define SCNoFAST8 "hho" +#define SCNoFAST16 __PRIFAST_RANK "o" +#define SCNoFAST32 __PRIFAST_RANK "o" +#define SCNoFAST64 __PRI64_RANK "o" + +#define SCNoMAX __PRI64_RANK "o" +#define SCNoPTR __PRIPTR_RANK "o" + +#define SCNu8 "hhu" +#define SCNu16 "hu" +#define SCNu32 "u" +#define SCNu64 __PRI64_RANK "u" + +#define SCNuLEAST8 "hhu" +#define SCNuLEAST16 "hu" +#define SCNuLEAST32 "u" +#define SCNuLEAST64 __PRI64_RANK "u" + +#define SCNuFAST8 "hhu" +#define SCNuFAST16 __PRIFAST_RANK "u" +#define SCNuFAST32 __PRIFAST_RANK "u" +#define SCNuFAST64 __PRI64_RANK "u" + +#define SCNuMAX __PRI64_RANK "u" +#define SCNuPTR __PRIPTR_RANK "u" + +#define SCNx8 "hhx" +#define SCNx16 "hx" +#define SCNx32 "x" +#define SCNx64 __PRI64_RANK "x" + +#define SCNxLEAST8 "hhx" +#define SCNxLEAST16 "hx" +#define SCNxLEAST32 "x" +#define SCNxLEAST64 __PRI64_RANK "x" + +#define SCNxFAST8 "hhx" +#define SCNxFAST16 __PRIFAST_RANK "x" +#define SCNxFAST32 __PRIFAST_RANK "x" +#define SCNxFAST64 __PRI64_RANK "x" + +#define SCNxMAX __PRI64_RANK "x" +#define SCNxPTR __PRIPTR_RANK "x" + +#endif + +#endif /* _INTTYPES_H */ diff --git a/klibc/klibc/include/klibc/compiler.h b/klibc/klibc/include/klibc/compiler.h new file mode 100644 index 0000000000..5c284b206c --- /dev/null +++ b/klibc/klibc/include/klibc/compiler.h @@ -0,0 +1,61 @@ +/* + * klibc/compiler.h + * + * Various compiler features + */ + +#ifndef _KLIBC_COMPILER_H +#define _KLIBC_COMPILER_H + +/* Specific calling conventions */ +#ifdef __i386__ +# ifdef __GNUC__ +# define __cdecl __attribute__((cdecl,regparm(0))) +# else + /* Most other C compilers have __cdecl as a keyword */ +# endif +#endif + +/* How to declare a function that *must* be inlined */ +#ifdef __GNUC__ +# if __GNUC_MAJOR__ >= 3 +# define __must_inline static __inline__ __attribute__((always_inline)) +# else +# define __must_inline extern __inline__ +# endif +#else +# define __must_inline inline /* Just hope this works... */ +#endif + +/* How to declare a function that does not return */ +#ifdef __GNUC__ +# define __noreturn void __attribute__((noreturn)) +#else +# define __noreturn void +#endif + +/* How to declare a "constant" function (a function in the + mathematical sense) */ +#ifdef __GNUC__ +# define __constfunc __attribute__((const)) +#else +# define __constfunc +#endif + +/* Format attribute */ +#ifdef __GNUC__ +# define __formatfunc(t,f,a) __attribute__((format(t,f,a))) +#else +# define __formatfunc(t,f,a) +#endif + +/* likely/unlikely */ +#if defined(__GNUC__) && (__GNUC_MAJOR__ > 2 || (__GNUC_MAJOR__ == 2 && __GNUC_MINOR__ >= 95)) +# define __likely(x) __builtin_expect((x), 1) +# define __unlikely(x) __builtin_expect((x), 0) +#else +# define __likely(x) (x) +# define __unlikely(x) (x) +#endif + +#endif diff --git a/klibc/klibc/include/klibc/diverr.h b/klibc/klibc/include/klibc/diverr.h new file mode 100644 index 0000000000..4d8c8d36c2 --- /dev/null +++ b/klibc/klibc/include/klibc/diverr.h @@ -0,0 +1,16 @@ +/* + * klibc/diverr.h + */ + +#ifndef _KLIBC_DIVERR_H +#define _KLIBC_DIVERR_H + +#include <signal.h> + +static __inline__ void +__divide_error(void) +{ + raise(SIGFPE); +} + +#endif /* _KLIBC_DIVERR_H */ diff --git a/klibc/klibc/include/klibc/extern.h b/klibc/klibc/include/klibc/extern.h new file mode 100644 index 0000000000..f9c3467211 --- /dev/null +++ b/klibc/klibc/include/klibc/extern.h @@ -0,0 +1,14 @@ +/* + * klibc/extern.h + */ + +#ifndef _KLIBC_EXTERN_H +#define _KLIBC_EXTERN_H + +#ifdef __cplusplus +#define __extern extern "C" +#else +#define __extern extern +#endif + +#endif /* _KLIBC_EXTERN_H */ diff --git a/klibc/klibc/include/limits.h b/klibc/klibc/include/limits.h new file mode 100644 index 0000000000..f1532e5323 --- /dev/null +++ b/klibc/klibc/include/limits.h @@ -0,0 +1,40 @@ +/* + * limits.h + */ + +#ifndef _LIMITS_H +#define _LIMITS_H + +#define CHAR_BIT 8 +#define SHRT_BIT 16 +#define INT_BIT 32 +#define LONGLONG_BIT 64 + +#define SCHAR_MIN (-128) +#define SCHAR_MAX 127 +#define UCHAR_MAX 255 + +#ifdef __CHAR_UNSIGNED__ +# define CHAR_MIN 0 +# define CHAR_MAX UCHAR_MAX +#else +# define CHAR_MIN SCHAR_MIN +# define CHAR_MAX SCHAR_MAX +#endif + +#define SHRT_MIN (-32768) +#define SHRT_MAX 32767 +#define USHRT_MAX 65535 + +#define INT_MIN (-2147483647-1) +#define INT_MAX 2147483647 +#define UINT_MAX 4294967295U + +#define LONGLONG_MIN (-9223372036854775807LL-1) +#define LONGLONG_MAX 9223372036854775807LL +#define ULONGLONG_MAX 18446744073709551615ULL + +#include <bitsize/limits.h> +#include <linux/limits.h> + +#endif /* _LIMITS_H */ diff --git a/klibc/klibc/include/net/if.h b/klibc/klibc/include/net/if.h new file mode 100644 index 0000000000..1aa8e7b90c --- /dev/null +++ b/klibc/klibc/include/net/if.h @@ -0,0 +1 @@ +#include <linux/if.h> diff --git a/klibc/klibc/include/net/if_arp.h b/klibc/klibc/include/net/if_arp.h new file mode 100644 index 0000000000..a25f1b4759 --- /dev/null +++ b/klibc/klibc/include/net/if_arp.h @@ -0,0 +1 @@ +#include <linux/if_arp.h> diff --git a/klibc/klibc/include/net/if_ether.h b/klibc/klibc/include/net/if_ether.h new file mode 100644 index 0000000000..060ef22070 --- /dev/null +++ b/klibc/klibc/include/net/if_ether.h @@ -0,0 +1 @@ +#include <linux/if_ether.h> diff --git a/klibc/klibc/include/net/if_packet.h b/klibc/klibc/include/net/if_packet.h new file mode 100644 index 0000000000..b5e8e0e11f --- /dev/null +++ b/klibc/klibc/include/net/if_packet.h @@ -0,0 +1 @@ +#include <linux/if_packet.h> diff --git a/klibc/klibc/include/netinet/in.h b/klibc/klibc/include/netinet/in.h new file mode 100644 index 0000000000..92dc843bb1 --- /dev/null +++ b/klibc/klibc/include/netinet/in.h @@ -0,0 +1,33 @@ +/* + * netinet/in.h + */ + +#ifndef _NETINET_IN_H +#define _NETINET_IN_H + +/* added this include by Mats Petersson */ +#include <linux/socket.h> + +#include <klibc/extern.h> +#include <stdint.h> +#include <endian.h> /* Must be included *before* <linux/in.h> */ +#include <linux/in.h> + +#ifndef htons +# define htons(x) __cpu_to_be16(x) +#endif +#ifndef ntohs +# define ntohs(x) __be16_to_cpu(x) +#endif +#ifndef htonl +# define htonl(x) __cpu_to_be32(x) +#endif +#ifndef ntohl +# define ntohl(x) __be32_to_cpu(x) +#endif + +#define IPPORT_RESERVED 1024 + +__extern int bindresvport (int sd, struct sockaddr_in *sin); + +#endif /* _NETINET_IN_H */ diff --git a/klibc/klibc/include/netinet/in6.h b/klibc/klibc/include/netinet/in6.h new file mode 100644 index 0000000000..46584ca627 --- /dev/null +++ b/klibc/klibc/include/netinet/in6.h @@ -0,0 +1,10 @@ +/* + * netinet/in6.h + */ + +#ifndef _NETINET_IN6_H +#define _NETINET_IN6_H + +#include <linux/in6.h> + +#endif /* _NETINET_IN6_H */ diff --git a/klibc/klibc/include/netinet/ip.h b/klibc/klibc/include/netinet/ip.h new file mode 100644 index 0000000000..8aecbe66a3 --- /dev/null +++ b/klibc/klibc/include/netinet/ip.h @@ -0,0 +1,13 @@ +/* + * netinet/ip.h + */ + +#ifndef _NETINET_IP_H +#define _NETINET_IP_H + +#include <endian.h> +#include <linux/ip.h> + +#define IP_DF 0x4000 /* Flag: "Don't Fragment" */ + +#endif /* _NETINET_IP_H */ diff --git a/klibc/klibc/include/netinet/tcp.h b/klibc/klibc/include/netinet/tcp.h new file mode 100644 index 0000000000..bb5d307e98 --- /dev/null +++ b/klibc/klibc/include/netinet/tcp.h @@ -0,0 +1,11 @@ +/* + * netinet/tcp.h + */ + +#ifndef _NETINET_TCP_H +#define _NETINET_TCP_H + +#include <endian.h> /* Include *before* linux/tcp.h */ +#include <linux/tcp.h> + +#endif /* _NETINET_TCP_H */ diff --git a/klibc/klibc/include/netinet/udp.h b/klibc/klibc/include/netinet/udp.h new file mode 100644 index 0000000000..b809b4ee6e --- /dev/null +++ b/klibc/klibc/include/netinet/udp.h @@ -0,0 +1,19 @@ +/* + * netinet/udp.h + */ + +#ifndef _NETINET_UDP_H +#define _NETINET_UDP_H + +/* + * We would include linux/udp.h, but it brings in too much other stuff + */ + +struct udphdr { + __u16 source; + __u16 dest; + __u16 len; + __u16 check; +}; + +#endif /* _NETINET_UDP_H */ diff --git a/klibc/klibc/include/poll.h b/klibc/klibc/include/poll.h new file mode 100644 index 0000000000..8710d92ebd --- /dev/null +++ b/klibc/klibc/include/poll.h @@ -0,0 +1,16 @@ +/* + * poll.h + */ + +#ifndef _POLL_H +#define _POLL_H + +#include <klibc/extern.h> +#include <linux/poll.h> + +/* POSIX specifies "int" for the timeout, Linux seems to use long... */ + +typedef unsigned int nfds_t; +__extern int poll(struct pollfd *, nfds_t, long); + +#endif /* _POLL_H */ diff --git a/klibc/klibc/include/sched.h b/klibc/klibc/include/sched.h new file mode 100644 index 0000000000..5e6103965f --- /dev/null +++ b/klibc/klibc/include/sched.h @@ -0,0 +1,23 @@ +/* + * sched.h + */ + +#ifndef _SCHED_H +#define _SCHED_H + +#include <klibc/extern.h> + +/* linux/sched.h is unusable; put the declarations we need here... */ + +#define SCHED_NORMAL 0 +#define SCHED_FIFO 1 +#define SCHED_RR 2 + +struct sched_param { + int sched_priority; +}; + +__extern int sched_setschedule(pid_t, int, const struct sched_param *); +__extern int sched_yield(void); + +#endif /* _SCHED_H */ diff --git a/klibc/klibc/include/setjmp.h b/klibc/klibc/include/setjmp.h new file mode 100644 index 0000000000..b504eb6d08 --- /dev/null +++ b/klibc/klibc/include/setjmp.h @@ -0,0 +1,43 @@ +/* + * setjmp.h + */ + +#ifndef _SETJMP_H +#define _SETJMP_H + +#include <klibc/extern.h> +#include <klibc/compiler.h> +#include <stddef.h> +#include <signal.h> + +#include <klibc/archsetjmp.h> + +__extern int setjmp(jmp_buf); +__extern __noreturn longjmp(jmp_buf, int); + +/* + Whose bright idea was it to add unrelated functionality to just about + the only function in the standard C library (setjmp) which cannot be + wrapped by an ordinary function wrapper? Anyway, the damage is done, + and therefore, this wrapper *must* be inline. However, gcc will + complain if this is an inline function for unknown reason, and + therefore sigsetjmp() needs to be a macro. +*/ + +struct __sigjmp_buf { + jmp_buf __jmpbuf; + sigset_t __sigs; +}; + +typedef struct __sigjmp_buf sigjmp_buf[1]; + +#define sigsetjmp(__env, __save) \ +({ \ + struct __sigjmp_buf *__e = (__env); \ + sigprocmask(0, NULL, &__e->__sigs); \ + setjmp(__e->__jmpbuf); \ +}) + +__extern __noreturn siglongjmp(sigjmp_buf, int); + +#endif /* _SETJMP_H */ diff --git a/klibc/klibc/include/signal.h b/klibc/klibc/include/signal.h new file mode 100644 index 0000000000..ffd2beba43 --- /dev/null +++ b/klibc/klibc/include/signal.h @@ -0,0 +1,72 @@ +/* + * signal.h + */ + +#ifndef _SIGNAL_H +#define _SIGNAL_H + +#include <klibc/extern.h> +#include <string.h> /* For memset() */ +#include <limits.h> /* For LONG_BIT */ +#include <sys/types.h> +#include <asm/signal.h> + +/* Some architectures don't define these */ +#ifndef SA_RESETHAND +# define SA_RESETHAND SA_ONESHOT +#endif +#ifndef SA_NODEFER +# define SA_NODEFER SA_NOMASK +#endif +#ifndef NSIG +# define NSIG _NSIG +#endif + +__extern const char * const sys_siglist[]; + +/* This assumes sigset_t is either an unsigned long or an array of such, + and that _NSIG_BPW in the kernel is always LONG_BIT */ + +static __inline__ int sigemptyset(sigset_t *__set) +{ + memset(__set, 0, sizeof *__set); + return 0; +} +static __inline__ int sigfillset(sigset_t *__set) +{ + memset(__set, ~0, sizeof *__set); + return 0; +} +static __inline__ int sigaddset(sigset_t *__set, int __signum) +{ + unsigned long *__lset = (unsigned long *)__set; + __lset[__signum/LONG_BIT] |= 1UL << (__signum%LONG_BIT); + return 0; +} +static __inline__ int sigdelset(sigset_t *__set, int __signum) +{ + unsigned long *__lset = (unsigned long *)__set; + __lset[__signum/LONG_BIT] &= ~(1UL << (__signum%LONG_BIT)); + return 0; +} +static __inline__ int sigismember(sigset_t *__set, int __signum) +{ + unsigned long *__lset = (unsigned long *)__set; + return (int)((__lset[__signum/LONG_BIT] >> (__signum%LONG_BIT)) & 1); +} + +__extern __sighandler_t __signal(int, __sighandler_t, int); +__extern __sighandler_t signal(int, __sighandler_t); +__extern __sighandler_t bsd_signal(int, __sighandler_t); +__extern int sigaction(int, const struct sigaction *, struct sigaction *); +__extern int sigprocmask(int, const sigset_t *, sigset_t *); +__extern int sigpending(sigset_t *); +__extern int sigsuspend(const sigset_t *); +__extern int rt_sigaction(int, const struct sigaction *, struct sigaction *, size_t); +__extern int rt_sigprocmask(int, const sigset_t *, sigset_t *, size_t); +__extern int rt_sigpending(sigset_t *, size_t); +__extern int rt_sigsuspend(const sigset_t *, size_t); +__extern int raise(int); +__extern int kill(pid_t, int); + +#endif /* _SIGNAL_H */ diff --git a/klibc/klibc/include/stdarg.h b/klibc/klibc/include/stdarg.h new file mode 100644 index 0000000000..cc324b825d --- /dev/null +++ b/klibc/klibc/include/stdarg.h @@ -0,0 +1,14 @@ +/* + * stdarg.h + * + * This is just a wrapper for the gcc one, but defines va_copy() + * even if gcc doesn't. + */ + +/* Note: the _STDARG_H macro belongs to the gcc header... */ +#include_next <stdarg.h> + +/* Older gcc considers this an extension, so it's double underbar only */ +#ifndef va_copy +#define va_copy(d,s) __va_copy(d,s) +#endif diff --git a/klibc/klibc/include/stddef.h b/klibc/klibc/include/stddef.h new file mode 100644 index 0000000000..900c147cd8 --- /dev/null +++ b/klibc/klibc/include/stddef.h @@ -0,0 +1,24 @@ +/* + * stddef.h + */ + +#ifndef _STDDEF_H +#define _STDDEF_H + +#ifndef __KLIBC__ +# define __KLIBC__ 1 +#endif + +#include <bitsize/stddef.h> + +#undef NULL +#ifdef __cplusplus +# define NULL 0 +#else +# define NULL ((void *)0) +#endif + +#undef offsetof +#define offsetof(t,m) ((size_t)&((t *)0->m)) + +#endif /* _STDDEF_H */ diff --git a/klibc/klibc/include/stdint.h b/klibc/klibc/include/stdint.h new file mode 100644 index 0000000000..2022a30fd7 --- /dev/null +++ b/klibc/klibc/include/stdint.h @@ -0,0 +1,113 @@ +/* + * stdint.h + */ + +#ifndef _STDINT_H +#define _STDINT_H + +#include <bitsize/stdint.h> + +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; + +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +typedef int8_t int_fast8_t; +typedef int64_t int_fast64_t; + +typedef uint8_t uint_fast8_t; +typedef uint64_t uint_fast64_t; + +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) + +#define INT8_MIN (-128) +#define INT16_MIN (-32768) +#define INT32_MIN (-2147483647-1) +#define INT64_MIN (__INT64_C(-9223372036854775807)-1) + +#define INT8_MAX (127) +#define INT16_MAX (32767) +#define INT32_MAX (2147483647) +#define INT64_MAX (__INT64_C(9223372036854775807)) + +#define UINT8_MAX (255U) +#define UINT16_MAX (65535U) +#define UINT32_MAX (4294967295U) +#define UINT64_MAX (__UINT64_C(18446744073709551615)) + +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST64_MIN INT64_MIN + +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MAX INT64_MAX + +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST64_MIN INT64_MIN + +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST64_MAX INT64_MAX + +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST64_MAX UINT64_MAX + +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +#include <bitsize/stdintlimits.h> + +#endif + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) + +#define INT8_C(c) c +#define INT16_C(c) c +#define INT32_C(c) c +#define INT64_C(c) __INT64_C(c) + +#define UINT8_C(c) c ## U +#define UINT16_C(c) c ## U +#define UINT32_C(c) c ## U +#define UINT64_C(c) __UINT64_C(c) + +#define INT_LEAST8_C(c) INT8_C(c) +#define INT_LEAST16_C(c) INT16_C(c) +#define INT_LEAST32_C(c) INT32_C(c) +#define INT_LEAST64_C(c) INT64_C(c) + +#define UINT_LEAST8_C(c) UINT8_C(c) +#define UINT_LEAST16_C(c) UINT16_C(c) +#define UINT_LEAST32_C(c) UINT32_C(c) +#define UINT_LEAST64_C(c) UINT64_C(c) + +#define INT_FAST8_C(c) INT8_C(c) +#define INT_FAST64_C(c) INT64_C(c) + +#define UINT_FAST8_C(c) UINT8_C(c) +#define UINT_FAST64_C(c) UINT64_C(c) + +#define INTMAX_C(c) INT64_C(c) +#define UINTMAX_C(c) UINT64_C(c) + +#include <bitsize/stdintconst.h> + +#endif + +#endif /* _STDINT_H */ diff --git a/klibc/klibc/include/stdio.h b/klibc/klibc/include/stdio.h new file mode 100644 index 0000000000..5e621af5f1 --- /dev/null +++ b/klibc/klibc/include/stdio.h @@ -0,0 +1,109 @@ +/* + * stdio.h + */ + +#ifndef _STDIO_H +#define _STDIO_H + +#include <klibc/extern.h> +#include <stdarg.h> +#include <stddef.h> +#include <unistd.h> + +/* This structure doesn't really exist, but it gives us something + to define FILE * with */ +struct _IO_file; +typedef struct _IO_file FILE; + +#define stdin ((FILE *)0) +#define stdout ((FILE *)1) +#define stderr ((FILE *)2) + +#ifndef EOF +# define EOF (-1) +#endif + +#ifndef BUFSIZ +# define BUFSIZ 4096 +#endif + +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 + +static __inline__ int fileno(FILE *__f) +{ + /* This should really be intptr_t, but size_t should be the same size */ + return (int)(size_t)__f; +} + +static __inline__ FILE * __create_file(int __fd) +{ + return (FILE *)(size_t)__fd; +} + +__extern FILE *fopen(const char *, const char *); + +static __inline__ FILE *fdopen(int __fd, const char *__m) +{ + (void)__m; return __create_file(__fd); +} +static __inline__ int fclose(FILE *__f) +{ + extern int close(int); + return close(fileno(__f)); +} +static __inline__ int fseek(FILE *__f, off_t __o, int __w) +{ + extern off_t lseek(int, off_t, int); + return (lseek(fileno(__f), __o, __w) == (off_t)-1) ? -1 : 0; +} +static __inline__ off_t ftell(FILE *__f) +{ + extern off_t lseek(int, off_t, int); + return lseek(fileno(__f), 0, SEEK_CUR); +} + +__extern int fputs(const char *, FILE *); +__extern int puts(const char *); +__extern int fputc(int, FILE *); +#define putc(c,f) fputc((c),(f)) +#define putchar(c) fputc((c),stdout) + +__extern int fgetc(FILE *); +__extern char * fgets(char *, int, FILE *); +#define getc(f) fgetc(f) + +__extern size_t _fread(void *, size_t, FILE *); +__extern size_t _fwrite(const void *, size_t, FILE *); + +#ifndef __NO_FREAD_FWRITE_INLINES +static __inline__ size_t +fread(void *__p, size_t __s, size_t __n, FILE *__f) +{ + return _fread(__p, __s*__n, __f)/__s; +} +static __inline__ size_t +fwrite(void *__p, size_t __s, size_t __n, FILE *__f) +{ + return _fwrite(__p, __s*__n, __f)/__s; +} +#endif + +__extern int printf(const char *, ...); +__extern int vprintf(const char *, va_list); +__extern int fprintf(FILE *, const char *, ...); +__extern int vfprintf(FILE *, const char *, va_list); +__extern int sprintf(char *, const char *, ...); +__extern int vsprintf(char *, const char *, va_list); +__extern int snprintf(char *, size_t n, const char *, ...); +__extern int vsnprintf(char *, size_t n, const char *, va_list); + +__extern int sscanf(const char *, const char *, ...); +__extern int vsscanf(const char *, const char *, va_list); + +__extern void perror(const char *); + +__extern int rename(const char *, const char *); + +#endif /* _STDIO_H */ diff --git a/klibc/klibc/include/stdlib.h b/klibc/klibc/include/stdlib.h new file mode 100644 index 0000000000..38dd1624a5 --- /dev/null +++ b/klibc/klibc/include/stdlib.h @@ -0,0 +1,94 @@ +/* + * stdlib.h + */ + +#ifndef _STDLIB_H +#define _STDLIB_H + +#include <klibc/extern.h> +#include <klibc/compiler.h> +#include <stddef.h> + +#define EXIT_FAILURE 1 +#define EXIT_SUCCESS 0 + +static __inline__ __noreturn _Exit(int __n) { + __extern __noreturn _exit(int); + _exit(__n); + for(;;); /* Some gcc versions are stupid */ +} +__extern __noreturn abort(void); +static __inline__ int abs(int __n) { + return (__n < 0) ? -__n : __n; +} +__extern int atexit(void (*)(void)); +__extern int on_exit(void (*)(int, void *), void *); +__extern int atoi(const char *); +__extern long atol(const char *); +__extern long long atoll(const char *); +__extern __noreturn exit(int); +__extern void free(void *); +static __inline__ long labs(long __n) { + return (__n < 0L) ? -__n : __n; +} + +static __inline__ long long llabs(long long __n) { + return (__n < 0LL) ? -__n : __n; +} + +#if defined(__GNUC__) && __GNUC_MAJOR__ >= 3 +# define __attribute_malloc __attribute__((malloc)) +#else +# define __attribute_malloc +#endif + +__extern __attribute_malloc void *malloc(size_t); +__extern __attribute_malloc void *calloc(size_t, size_t); +__extern void *realloc(void *, size_t); +__extern long strtol(const char *, char **, int); +__extern long long strtoll(const char *, char **, int); +__extern unsigned long strtoul(const char *, char **, int); +__extern unsigned long long strtoull(const char *, char **, int); + +__extern char *getenv(const char *); +__extern int putenv(const char *); +__extern int setenv(const char *, const char *, int); +__extern int unsetenv(const char *); + +__extern void qsort(void *, size_t, size_t, int (*)(const void *, const void *)); + + +__extern long jrand48(unsigned short *); +__extern long mrand48(void); +__extern long nrand48(unsigned short *); +__extern long lrand48(void); +__extern unsigned short *seed48(const unsigned short *); +__extern void srand48(long); + +#define RAND_MAX 0x7fffffff +static __inline__ int rand(void) { + return (int)lrand48(); +} +static __inline__ void srand(unsigned int __s) { + srand48(__s); +} +static __inline__ long random(void) +{ + return lrand48(); +} +static __inline__ void srandom(unsigned int __s) +{ + srand48(__s); +} + +/* Basic PTY functions. These only work if devpts is mounted! */ + +static __inline__ int grantpt(int __fd) +{ + (void)__fd; + return 0; /* devpts does this all for us! */ +} +__extern int unlockpt(int); +__extern char *ptsname(int); + +#endif /* _STDLIB_H */ diff --git a/klibc/klibc/include/string.h b/klibc/klibc/include/string.h new file mode 100644 index 0000000000..bce69284ec --- /dev/null +++ b/klibc/klibc/include/string.h @@ -0,0 +1,37 @@ +/* + * string.h + */ + +#ifndef _STRING_H +#define _STRING_H + +#include <klibc/extern.h> +#include <stddef.h> + +__extern void *memccpy(void *, const void *, int, size_t); +__extern void *memchr(const void *, int, size_t); +__extern int memcmp(const void *, const void *, size_t); +__extern void *memcpy(void *, const void *, size_t); +__extern void *memmove(void *, const void *, size_t); +__extern void *memset(void *, int, size_t); +__extern void *memmem(const void *, size_t, const void *, size_t); +__extern void memswap(void *, void *, size_t); +__extern char *strcat(char *, const char *); +__extern char *strchr(const char *, int); +__extern int strcmp(const char *, const char *); +__extern char *strcpy(char *, const char *); +__extern size_t strcspn(const char *, const char *); +__extern char *strdup(const char *); +__extern char *strerror(int); +__extern size_t strlen(const char *); +__extern char *strncat(char *, const char *, size_t); +__extern int strncmp(const char *, const char *, size_t); +__extern char *strncpy(char *, const char *, size_t); +__extern char *strpbrk(const char *, const char *); +__extern char *strrchr(const char *, int); +__extern char *strsep(char **, const char *); +__extern size_t strspn(const char *, const char *); +__extern char *strstr(const char *, const char *); +__extern char *strtok(char *, const char *); + +#endif /* _STRING_H */ diff --git a/klibc/klibc/include/sys/dirent.h b/klibc/klibc/include/sys/dirent.h new file mode 100644 index 0000000000..0700f4b561 --- /dev/null +++ b/klibc/klibc/include/sys/dirent.h @@ -0,0 +1,13 @@ +/* + * sys/dirent.h + */ + +#ifndef _SYS_DIRENT_H +#define _SYS_DIRENT_H + +#include <sys/types.h> +#include <linux/dirent.h> + +__extern int getdents(unsigned int, struct dirent *, unsigned int); + +#endif /* _SYS_DIRENT_H */ diff --git a/klibc/klibc/include/sys/fsuid.h b/klibc/klibc/include/sys/fsuid.h new file mode 100644 index 0000000000..823486b776 --- /dev/null +++ b/klibc/klibc/include/sys/fsuid.h @@ -0,0 +1,14 @@ +/* + * sys/fsuid.h + */ + +#ifndef _SYS_FSUID_H +#define _SYS_FSUID_H + +#include <klibc/extern.h> +#include <sys/types.h> + +__extern int setfsuid(uid_t); +__extern int setfsgid(gid_t); + +#endif /* _SYS_FSUID_H */ diff --git a/klibc/klibc/include/sys/ioctl.h b/klibc/klibc/include/sys/ioctl.h new file mode 100644 index 0000000000..b0cee4c02c --- /dev/null +++ b/klibc/klibc/include/sys/ioctl.h @@ -0,0 +1,14 @@ +/* + * sys/ioctl.h + */ + +#ifndef _SYS_IOCTL_H +#define _SYS_IOCTL_H + +#include <klibc/extern.h> +#include <linux/ioctl.h> +#include <asm/ioctls.h> + +__extern int ioctl(int, int, void *); + +#endif /* _SYS_IOCTL_H */ diff --git a/klibc/klibc/include/sys/klog.h b/klibc/klibc/include/sys/klog.h new file mode 100644 index 0000000000..0fc5f5d945 --- /dev/null +++ b/klibc/klibc/include/sys/klog.h @@ -0,0 +1,24 @@ +/* + * sys/klog.h + */ + +#ifndef _SYS_KLOG_H +#define _SYS_KLOG_H + +#include <klibc/extern.h> + +#define KLOG_CLOSE 0 +#define KLOG_OPEN 1 +#define KLOG_READ 2 +#define KLOG_READ_ALL 3 +#define KLOG_READ_CLEAR 4 +#define KLOG_CLEAR 5 +#define KLOG_DISABLE 6 +#define KLOG_ENABLE 7 +#define KLOG_SETLEVEL 8 +#define KLOG_UNREADSIZE 9 +#define KLOG_WRITE 10 + +__extern int klogctl(int, char *, int); + +#endif /* _SYS_KLOG_H */ diff --git a/klibc/klibc/include/sys/mman.h b/klibc/klibc/include/sys/mman.h new file mode 100644 index 0000000000..3d8a2f63c2 --- /dev/null +++ b/klibc/klibc/include/sys/mman.h @@ -0,0 +1,21 @@ +/* + * sys/mman.h + */ + +#ifndef _SYS_MMAN_H +#define _SYS_MMAN_H + +#include <klibc/extern.h> +#include <sys/types.h> +#include <asm/mman.h> +#include <asm/page.h> /* For PAGE_SIZE */ + +#define MAP_FAILED ((void *)-1) + +__extern void *mmap(void *, size_t, int, int, int, off_t); +__extern int munmap(void *, size_t); +__extern void *mremap(void *, size_t, size_t, unsigned long); +__extern int msync(const void *, size_t, int); +__extern int mprotect(const void *, size_t, int); + +#endif /* _SYS_MMAN_H */ diff --git a/klibc/klibc/include/sys/module.h b/klibc/klibc/include/sys/module.h new file mode 100644 index 0000000000..96b3b59945 --- /dev/null +++ b/klibc/klibc/include/sys/module.h @@ -0,0 +1,158 @@ +/* + * sys/module.h + * + * This is a bastardized version of linux/module.h, since the latter + * doesn't have __KERNEL__ guards where it needs them... + */ + +#ifndef _SYS_MODULE_H +#define _SYS_MODULE_H + +/* + * Dynamic loading of modules into the kernel. + * + * Rewritten by Richard Henderson <rth@tamu.edu> Dec 1996 + */ + +#include <asm/atomic.h> + +/* Don't need to bring in all of uaccess.h just for this decl. */ +struct exception_table_entry; + +/* Used by get_kernel_syms, which is obsolete. */ +struct kernel_sym +{ + unsigned long value; + char name[60]; /* should have been 64-sizeof(long); oh well */ +}; + +struct module_symbol +{ + unsigned long value; + const char *name; +}; + +struct module_ref +{ + struct module *dep; /* "parent" pointer */ + struct module *ref; /* "child" pointer */ + struct module_ref *next_ref; +}; + +/* TBD */ +struct module_persist; + +struct module +{ + unsigned long size_of_struct; /* == sizeof(module) */ + struct module *next; + const char *name; + unsigned long size; + + union + { + atomic_t usecount; + long pad; + } uc; /* Needs to keep its size - so says rth */ + + unsigned long flags; /* AUTOCLEAN et al */ + + unsigned nsyms; + unsigned ndeps; + + struct module_symbol *syms; + struct module_ref *deps; + struct module_ref *refs; + int (*init)(void); + void (*cleanup)(void); + const struct exception_table_entry *ex_table_start; + const struct exception_table_entry *ex_table_end; +#ifdef __alpha__ + unsigned long gp; +#endif + /* Members past this point are extensions to the basic + module support and are optional. Use mod_member_present() + to examine them. */ + const struct module_persist *persist_start; + const struct module_persist *persist_end; + int (*can_unload)(void); + int runsize; /* In modutils, not currently used */ + const char *kallsyms_start; /* All symbols for kernel debugging */ + const char *kallsyms_end; + const char *archdata_start; /* arch specific data for module */ + const char *archdata_end; + const char *kernel_data; /* Reserved for kernel internal use */ +}; + +struct module_info +{ + unsigned long addr; + unsigned long size; + unsigned long flags; + long usecount; +}; + +/* Bits of module.flags. */ + +#define MOD_UNINITIALIZED 0 +#define MOD_RUNNING 1 +#define MOD_DELETED 2 +#define MOD_AUTOCLEAN 4 +#define MOD_VISITED 8 +#define MOD_USED_ONCE 16 +#define MOD_JUST_FREED 32 +#define MOD_INITIALIZING 64 + +/* Values for query_module's which. */ + +#define QM_MODULES 1 +#define QM_DEPS 2 +#define QM_REFS 3 +#define QM_SYMBOLS 4 +#define QM_INFO 5 + +/* Can the module be queried? */ +#define MOD_CAN_QUERY(mod) (((mod)->flags & (MOD_RUNNING | MOD_INITIALIZING)) && !((mod)->flags & MOD_DELETED)) + +/* When struct module is extended, we must test whether the new member + is present in the header received from insmod before we can use it. + This function returns true if the member is present. */ + +#define mod_member_present(mod,member) \ + ((unsigned long)(&((struct module *)0L)->member + 1) \ + <= (mod)->size_of_struct) + +/* + * Ditto for archdata. Assumes mod->archdata_start and mod->archdata_end + * are validated elsewhere. + */ +#define mod_archdata_member_present(mod, type, member) \ + (((unsigned long)(&((type *)0L)->member) + \ + sizeof(((type *)0L)->member)) <= \ + ((mod)->archdata_end - (mod)->archdata_start)) + + +/* Check if an address p with number of entries n is within the body of module m */ +#define mod_bound(p, n, m) ((unsigned long)(p) >= ((unsigned long)(m) + ((m)->size_of_struct)) && \ + (unsigned long)((p)+(n)) <= (unsigned long)(m) + (m)->size) + +/* Backwards compatibility definition. */ + +#define GET_USE_COUNT(module) (atomic_read(&(module)->uc.usecount)) + +/* Poke the use count of a module. */ + +#define __MOD_INC_USE_COUNT(mod) \ + (atomic_inc(&(mod)->uc.usecount), (mod)->flags |= MOD_VISITED|MOD_USED_ONCE) +#define __MOD_DEC_USE_COUNT(mod) \ + (atomic_dec(&(mod)->uc.usecount), (mod)->flags |= MOD_VISITED) +#define __MOD_IN_USE(mod) \ + (mod_member_present((mod), can_unload) && (mod)->can_unload \ + ? (mod)->can_unload() : atomic_read(&(mod)->uc.usecount)) + +/* Indirect stringification. */ + +#define __MODULE_STRING_1(x) #x +#define __MODULE_STRING(x) __MODULE_STRING_1(x) + +#endif /* _SYS_MODULE_H */ diff --git a/klibc/klibc/include/sys/mount.h b/klibc/klibc/include/sys/mount.h new file mode 100644 index 0000000000..313c90ec0e --- /dev/null +++ b/klibc/klibc/include/sys/mount.h @@ -0,0 +1,55 @@ +/* + * sys/mount.h + */ + +#ifndef _SYS_MOUNT_H +#define _SYS_MOUNT_H + +#include <klibc/extern.h> + +/* + * These are the fs-independent mount-flags: up to 32 flags are supported + */ +#define MS_RDONLY 1 /* Mount read-only */ +#define MS_NOSUID 2 /* Ignore suid and sgid bits */ +#define MS_NODEV 4 /* Disallow access to device special files */ +#define MS_NOEXEC 8 /* Disallow program execution */ +#define MS_SYNCHRONOUS 16 /* Writes are synced at once */ +#define MS_REMOUNT 32 /* Alter flags of a mounted FS */ +#define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */ +#define MS_DIRSYNC 128 /* Directory modifications are synchronous */ +#define MS_NOATIME 1024 /* Do not update access times. */ +#define MS_NODIRATIME 2048 /* Do not update directory access times */ +#define MS_BIND 4096 +#define MS_MOVE 8192 +#define MS_REC 16384 +#define MS_VERBOSE 32768 +#define MS_NOUSER (1<<31) + +/* + * Superblock flags that can be altered by MS_REMOUNT + */ +#define MS_RMT_MASK (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_NOATIME|MS_NODIRATIME) + +/* + * Old magic mount flag and mask + */ +#define MS_MGC_VAL 0xC0ED0000 +#define MS_MGC_MSK 0xffff0000 + +/* + * umount2() flags + */ +#define MNT_FORCE 1 + +/* + * Prototypes + */ +__extern int mount(const char *, const char *, + const char *, unsigned long, + const void *); +__extern int umount(const char *); +__extern int umount2(const char *, int); +__extern int pivot_root(const char *, const char *); + +#endif /* _SYS_MOUNT_H */ diff --git a/klibc/klibc/include/sys/param.h b/klibc/klibc/include/sys/param.h new file mode 100644 index 0000000000..63a0661f43 --- /dev/null +++ b/klibc/klibc/include/sys/param.h @@ -0,0 +1,11 @@ +/* + * sys/param.h + */ + +#ifndef _SYS_PARAM_H +#define _SYS_PARAM_H + +#include <limits.h> +#include <linux/param.h> + +#endif /* _SYS_PARAM_H */ diff --git a/klibc/klibc/include/sys/reboot.h b/klibc/klibc/include/sys/reboot.h new file mode 100644 index 0000000000..eaf56610d7 --- /dev/null +++ b/klibc/klibc/include/sys/reboot.h @@ -0,0 +1,25 @@ +/* + * sys/reboot.h + */ + +#ifndef _SYS_REBOOT_H +#define _SYS_REBOOT_H + +#include <klibc/extern.h> +#include <linux/reboot.h> + +/* glibc names these constants differently; allow both versions */ + +#define RB_AUTOBOOT LINUX_REBOOT_CMD_RESTART +#define RB_HALT_SYSTEM LINUX_REBOOT_CMD_HALT +#define RB_ENABLE_CAD LINUX_REBOOT_CMD_CAD_ON +#define RB_DISABLE_CAD LINUX_REBOOT_CMD_CAD_OFF +#define RB_POWER_OFF LINUX_REBOOT_CMD_POWER_OFF + +/* glibc-ish one-argument version */ +__extern int reboot(int); + +/* Native four-argument system call */ +__extern int __reboot(int, int, int, void *); + +#endif /* _SYS_REBOOT_H */ diff --git a/klibc/klibc/include/sys/resource.h b/klibc/klibc/include/sys/resource.h new file mode 100644 index 0000000000..ef14bde9f6 --- /dev/null +++ b/klibc/klibc/include/sys/resource.h @@ -0,0 +1,15 @@ +/* + * sys/resource.h + */ + +#ifndef _SYS_RESOURCE_H +#define _SYS_RESOURCE_H + +#include <klibc/extern.h> +#include <sys/types.h> /* MUST be included before linux/resource.h */ +#include <linux/resource.h> + +__extern int getpriority(int, int); +__extern int setpriority(int, int, int); + +#endif /* _SYS_RESOURCE_H */ diff --git a/klibc/klibc/include/sys/select.h b/klibc/klibc/include/sys/select.h new file mode 100644 index 0000000000..7caf8c931b --- /dev/null +++ b/klibc/klibc/include/sys/select.h @@ -0,0 +1,13 @@ +/* + * sys/select.h + */ + +#ifndef _SYS_SELECT_H +#define _SYS_SELECT_H + +#include <sys/time.h> +#include <sys/types.h> + +__extern int select(int, fd_set *, fd_set *, fd_set *, struct timeval *); + +#endif /* _SYS_SELECT_H */ diff --git a/klibc/klibc/include/sys/socket.h b/klibc/klibc/include/sys/socket.h new file mode 100644 index 0000000000..cbc2b89591 --- /dev/null +++ b/klibc/klibc/include/sys/socket.h @@ -0,0 +1,50 @@ +/* + * sys/socket.h + */ + +#ifndef _SYS_SOCKET_H +#define _SYS_SOCKET_H + +#include <klibc/extern.h> +#include <klibc/compiler.h> +#include <linux/socket.h> + +/* For some reason these may be protected by __KERNEL__ in asm/socket.h */ +#ifndef SOCK_STREAM +# define SOCK_STREAM 1 +# define SOCK_DGRAM 2 +# define SOCK_RAW 3 +# define SOCK_RDM 4 +# define SOCK_SEQPACKET 5 +# define SOCK_PACKET 10 +#endif + +#ifdef __i386__ +# define __socketcall __extern __cdecl +#else +# define __socketcall __extern +#endif + +typedef int socklen_t; + +__socketcall int socket(int, int, int); +__socketcall int bind(int, struct sockaddr *, int); +__socketcall int connect(int, struct sockaddr *, socklen_t); +__socketcall int listen(int, int); +__socketcall int accept(int, struct sockaddr *, socklen_t *); +__socketcall int getsockname(int, struct sockaddr *, socklen_t *); +__socketcall int getpeername(int, struct sockaddr *, socklen_t *); +__socketcall int socketpair(int, int, int, int *); +__extern int send(int, const void *, size_t, unsigned int); +__socketcall int sendto(int, const void *, size_t, int, const struct sockaddr *, socklen_t); +__extern int recv(int, void *, size_t, unsigned int); +__socketcall int recvfrom(int, void *, size_t, unsigned int, struct sockaddr *, socklen_t *); +__socketcall int shutdown(int, int); +__socketcall int setsockopt(int, int, int, const void *, socklen_t); +__socketcall int getsockopt(int, int, int, void *, socklen_t *); +__socketcall int sendmsg(int, const struct msghdr *, unsigned int); +__socketcall int recvmsg(int, struct msghdr *, unsigned int); + +#undef __socketcall + +#endif /* _SYS_SOCKET_H */ diff --git a/klibc/klibc/include/sys/socketcalls.h b/klibc/klibc/include/sys/socketcalls.h new file mode 100644 index 0000000000..dac9f9aab6 --- /dev/null +++ b/klibc/klibc/include/sys/socketcalls.h @@ -0,0 +1,28 @@ +/* + * sys/socketcalls.h + */ + +#ifndef _SYS_SOCKETCALLS_H +#define _SYS_SOCKETCALLS_H + +/* socketcalls by number, since <linux/net.h> isn't usable for assembly */ + +#define SYS_SOCKET 1 /* sys_socket(2) */ +#define SYS_BIND 2 /* sys_bind(2) */ +#define SYS_CONNECT 3 /* sys_connect(2) */ +#define SYS_LISTEN 4 /* sys_listen(2) */ +#define SYS_ACCEPT 5 /* sys_accept(2) */ +#define SYS_GETSOCKNAME 6 /* sys_getsockname(2) */ +#define SYS_GETPEERNAME 7 /* sys_getpeername(2) */ +#define SYS_SOCKETPAIR 8 /* sys_socketpair(2) */ +#define SYS_SEND 9 /* sys_send(2) */ +#define SYS_RECV 10 /* sys_recv(2) */ +#define SYS_SENDTO 11 /* sys_sendto(2) */ +#define SYS_RECVFROM 12 /* sys_recvfrom(2) */ +#define SYS_SHUTDOWN 13 /* sys_shutdown(2) */ +#define SYS_SETSOCKOPT 14 /* sys_setsockopt(2) */ +#define SYS_GETSOCKOPT 15 /* sys_getsockopt(2) */ +#define SYS_SENDMSG 16 /* sys_sendmsg(2) */ +#define SYS_RECVMSG 17 /* sys_recvmsg(2) */ + +#endif /* _SYS_SOCKETCALLS_H */ diff --git a/klibc/klibc/include/sys/stat.h b/klibc/klibc/include/sys/stat.h new file mode 100644 index 0000000000..f7bb5aacc5 --- /dev/null +++ b/klibc/klibc/include/sys/stat.h @@ -0,0 +1,23 @@ +/* + * sys/stat.h + */ + +#ifndef _SYS_STAT_H +#define _SYS_STAT_H + +#include <klibc/extern.h> +#include <sys/types.h> +#include <asm/stat.h> +#include <linux/stat.h> + +__extern int stat(const char *, struct stat *); +__extern int fstat(int, struct stat *); +__extern int lstat(const char *, struct stat *); +__extern mode_t umask(mode_t); +__extern int mknod(const char *, mode_t, dev_t); +static __inline__ int mkfifo(const char *__p, mode_t __m) +{ + return mknod(__p, (__m & ~S_IFMT) | S_IFIFO, (dev_t)0); +} + +#endif /* _SYS_STAT_H */ diff --git a/klibc/klibc/include/sys/syscall.h b/klibc/klibc/include/sys/syscall.h new file mode 100644 index 0000000000..907c7f9b9a --- /dev/null +++ b/klibc/klibc/include/sys/syscall.h @@ -0,0 +1,15 @@ +/* + * sys/syscall.h + * + * Generic system call interface macros + */ +#ifndef _SYS_SYSCALL_H +#define _SYS_SYSCALL_H + +#include <errno.h> +#include <asm/unistd.h> + +/* Many architectures have incomplete or defective syscall macros */ +#include <klibc/archsys.h> + +#endif /* _SYS_SYSCALL_H */ diff --git a/klibc/klibc/include/sys/time.h b/klibc/klibc/include/sys/time.h new file mode 100644 index 0000000000..4eccf824a4 --- /dev/null +++ b/klibc/klibc/include/sys/time.h @@ -0,0 +1,16 @@ +/* + * sys/time.h + */ + +#ifndef _SYS_TIME_H +#define _SYS_TIME_H + +#include <klibc/extern.h> +#include <linux/time.h> + +__extern int gettimeofday(struct timeval *, struct timezone *); +__extern int settimeofday(const struct timeval *, const struct timezone *); +__extern int getitimer(int, struct itimerval *); +__extern int setitimer(int, const struct itimerval *, struct itimerval *); + +#endif /* _SYS_TIME_H */ diff --git a/klibc/klibc/include/sys/times.h b/klibc/klibc/include/sys/times.h new file mode 100644 index 0000000000..657f9c4b1c --- /dev/null +++ b/klibc/klibc/include/sys/times.h @@ -0,0 +1,14 @@ +/* + * sys/times.h + */ + +#ifndef _SYS_TIMES_H +#define _SYS_TIMES_H + +#include <linux/times.h> + +__extern clock_t times(struct tms *); +__extern int gettimeofday(struct timeval *, struct timezone *); +__extern int settimeofday(const struct timeval *, const struct timezone *); + +#endif /* _SYS_TIMES_H */ diff --git a/klibc/klibc/include/sys/types.h b/klibc/klibc/include/sys/types.h new file mode 100644 index 0000000000..a25873cc4b --- /dev/null +++ b/klibc/klibc/include/sys/types.h @@ -0,0 +1,127 @@ +/* + * sys/types.h + * + * This is a bastardized version of linux/types.h, since that file + * is broken w.r.t. <stdint.h> definitions. + */ + +#ifndef _SYS_TYPES_H +#define _SYS_TYPES_H + +#include <stddef.h> +#include <stdint.h> + +#define _SSIZE_T +typedef ptrdiff_t ssize_t; + +#include <linux/posix_types.h> +#include <asm/types.h> + +/* Keeps linux/types.h from getting included elsewhere */ +#define _LINUX_TYPES_H + +typedef __kernel_fd_set fd_set; +typedef uint32_t dev_t; +typedef __kernel_ino_t ino_t; +typedef __kernel_mode_t mode_t; +typedef __kernel_nlink_t nlink_t; +typedef __kernel_off_t off_t; +typedef __kernel_pid_t pid_t; +typedef __kernel_daddr_t daddr_t; +typedef __kernel_key_t key_t; +typedef __kernel_suseconds_t suseconds_t; +typedef __kernel_timer_t timer_t; + +typedef __kernel_uid32_t uid_t; +typedef __kernel_gid32_t gid_t; + +typedef __kernel_loff_t loff_t; + +/* + * The following typedefs are also protected by individual ifdefs for + * historical reasons: + */ +#ifndef _SIZE_T +#define _SIZE_T +typedef __kernel_size_t size_t; +#endif + +#ifndef _SSIZE_T +#define _SSIZE_T +typedef __kernel_ssize_t ssize_t; +#endif + +#ifndef _PTRDIFF_T +#define _PTRDIFF_T +typedef __kernel_ptrdiff_t ptrdiff_t; +#endif + +#ifndef _TIME_T +#define _TIME_T +typedef __kernel_time_t time_t; +#endif + +#ifndef _CLOCK_T +#define _CLOCK_T +typedef __kernel_clock_t clock_t; +#endif + +#ifndef _CADDR_T +#define _CADDR_T +typedef __kernel_caddr_t caddr_t; +#endif + +/* bsd */ +typedef unsigned char u_char; +typedef unsigned short u_short; +typedef unsigned int u_int; +typedef unsigned long u_long; + +/* sysv */ +typedef unsigned char unchar; +typedef unsigned short ushort; +typedef unsigned int uint; +typedef unsigned long ulong; + +#ifndef __BIT_TYPES_DEFINED__ +#define __BIT_TYPES_DEFINED__ + +typedef __u8 u_int8_t; +typedef __u16 u_int16_t; +typedef __u32 u_int32_t; +typedef __u64 u_int64_t; + +#endif /* !(__BIT_TYPES_DEFINED__) */ + +/* + * transition to 64-bit sector_t, possibly making it an option... + */ +#undef BLK_64BIT_SECTOR + +#ifdef BLK_64BIT_SECTOR +typedef u64 sector_t; +#else +typedef unsigned long sector_t; +#endif + +/* + * The type of an index into the pagecache. Use a #define so asm/types.h + * can override it. + */ +#ifndef pgoff_t +#define pgoff_t unsigned long +#endif + +/* + * Below are truly Linux-specific types that should never collide with + * any application/library that wants linux/types.h. + */ + +struct ustat { + __kernel_daddr_t f_tfree; + __kernel_ino_t f_tinode; + char f_fname[6]; + char f_fpack[6]; +}; + +#endif diff --git a/klibc/klibc/include/sys/uio.h b/klibc/klibc/include/sys/uio.h new file mode 100644 index 0000000000..fc2525d11a --- /dev/null +++ b/klibc/klibc/include/sys/uio.h @@ -0,0 +1,15 @@ +/* + * sys/uio.h + */ + +#ifndef _SYS_UIO_H +#define _SYS_UIO_H + +#include <klibc/extern.h> +#include <sys/types.h> +#include <linux/uio.h> + +__extern int readv(int, const struct iovec *, int); +__extern int writev(int, const struct iovec *, int); + +#endif /* _SYS_UIO_H */ diff --git a/klibc/klibc/include/sys/utime.h b/klibc/klibc/include/sys/utime.h new file mode 100644 index 0000000000..d1d635d242 --- /dev/null +++ b/klibc/klibc/include/sys/utime.h @@ -0,0 +1,10 @@ +/* + * sys/utime.h + */ + +#ifndef _SYS_UTIME_H +#define _SYS_UTIME_H + +#include <linux/utime.h> + +#endif /* _SYS_UTIME_H */ diff --git a/klibc/klibc/include/sys/utsname.h b/klibc/klibc/include/sys/utsname.h new file mode 100644 index 0000000000..f2990f5711 --- /dev/null +++ b/klibc/klibc/include/sys/utsname.h @@ -0,0 +1,23 @@ +/* + * sys/utsname.h + */ + +#ifndef _SYS_UTSNAME_H +#define _SYS_UTSNAME_H + +#include <klibc/extern.h> + +#define SYS_NMLN 65 + +struct utsname { + char sysname[SYS_NMLN]; + char nodename[SYS_NMLN]; + char release[SYS_NMLN]; + char version[SYS_NMLN]; + char machine[SYS_NMLN]; + char domainname[SYS_NMLN]; +}; + +__extern int uname(struct utsname *); + +#endif /* _SYS_UTSNAME_H */ diff --git a/klibc/klibc/include/sys/vfs.h b/klibc/klibc/include/sys/vfs.h new file mode 100644 index 0000000000..8c1577c4bf --- /dev/null +++ b/klibc/klibc/include/sys/vfs.h @@ -0,0 +1,14 @@ +/* + * sys/vfs.h + */ + +#ifndef _SYS_VFS_H +#define _SYS_VFS_H + +#include <klibc/extern.h> +#include <linux/vfs.h> + +__extern int statfs(const char *, struct statfs *); +__extern int fstatfs(int, struct statfs *); + +#endif /* _SYS_VFS_H */ diff --git a/klibc/klibc/include/sys/wait.h b/klibc/klibc/include/sys/wait.h new file mode 100644 index 0000000000..cad6989bf7 --- /dev/null +++ b/klibc/klibc/include/sys/wait.h @@ -0,0 +1,19 @@ +/* + * sys/wait.h + */ + +#ifndef _SYS_WAIT_H +#define _SYS_WAIT_H + +#include <klibc/extern.h> +#include <sys/types.h> +#include <sys/resource.h> + +#include <linux/wait.h> + +__extern pid_t wait(int *); +__extern pid_t waitpid(pid_t, int *, int); +__extern pid_t wait3(int *, int, struct rusage *); +__extern pid_t wait4(pid_t, int *, int, struct rusage *); + +#endif /* _SYS_WAIT_H */ diff --git a/klibc/klibc/include/syslog.h b/klibc/klibc/include/syslog.h new file mode 100644 index 0000000000..b6c0acfea1 --- /dev/null +++ b/klibc/klibc/include/syslog.h @@ -0,0 +1,53 @@ +/* + * syslog.h + */ + +#ifndef _SYSLOG_H +#define _SYSLOG_H + +#include <klibc/extern.h> + +/* Alert levels */ +#define LOG_EMERG 0 +#define LOG_ALERT 1 +#define LOG_CRIT 2 +#define LOG_ERR 3 +#define LOG_WARNING 4 +#define LOG_NOTICE 5 +#define LOG_INFO 6 +#define LOG_DEBUG 7 + +#define LOG_PRIMASK 7 +#define LOG_PRI(x) ((x) & LOG_PRIMASK) + + +/* Facilities; not actually used */ +#define LOG_KERN 0000 +#define LOG_USER 0010 +#define LOG_MAIL 0020 +#define LOG_DAEMON 0030 +#define LOG_AUTH 0040 +#define LOG_SYSLOG 0050 +#define LOG_LPR 0060 +#define LOG_NEWS 0070 +#define LOG_UUCP 0100 +#define LOG_CRON 0110 +#define LOG_AUTHPRIV 0120 +#define LOG_FTP 0130 +#define LOG_LOCAL0 0200 +#define LOG_LOCAL1 0210 +#define LOG_LOCAL2 0220 +#define LOG_LOCAL3 0230 +#define LOG_LOCAL4 0240 +#define LOG_LOCAL5 0250 +#define LOG_LOCAL6 0260 +#define LOG_LOCAL7 0270 + +#define LOG_FACMASK 01770 +#define LOG_FAC(x) (((x) >> 3) & (LOG_FACMASK >> 3)) + +__extern void openlog(const char *, int, int); +__extern void syslog(int, const char *, ...); +__extern void closelog(void); + +#endif /* _SYSLOG_H */ diff --git a/klibc/klibc/include/termios.h b/klibc/klibc/include/termios.h new file mode 100644 index 0000000000..08a5e56855 --- /dev/null +++ b/klibc/klibc/include/termios.h @@ -0,0 +1,86 @@ +/* + * termios.h + */ + +#ifndef _TERMIOS_H +#define _TERMIOS_H + +#include <klibc/extern.h> +#include <stdint.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <linux/termios.h> + +/* Redefine these so the magic constants == the ioctl number to use. */ +#undef TCSANOW +#undef TCSADRAIN +#undef TCSAFLUSH +#define TCSANOW TCSETS +#define TCSADRAIN TCSETSW +#define TCSAFLUSH TCSETSF + +static __inline__ int tcgetattr(int __fd, struct termios *__s) +{ + return ioctl(__fd, TCGETS, __s); +} + +static __inline__ int tcsetattr(int __fd, int __opt, const struct termios *__s) +{ + return ioctl(__fd, __opt, (void *)__s); +} + +static __inline__ int tcflow(int __fd, int __action) +{ + return ioctl(__fd, TCXONC, (void *)(intptr_t)__action); +} + +static __inline__ int tcflush(int __fd, int __queue) +{ + return ioctl(__fd, TCFLSH, (void *)(intptr_t)__queue); +} + +static __inline__ pid_t tcgetpgrp(int __fd) +{ + pid_t __p; + return ioctl(__fd, TIOCGPGRP, &__p) ? (pid_t)-1 : __p; +} + +static __inline__ pid_t tcgetsid(int __fd) +{ + pid_t __p; + return ioctl(__fd, TIOCGSID, &__p) ? (pid_t)-1 : __p; +} + +static __inline__ int tcsendbreak(int __fd, int __duration) +{ + return ioctl(__fd, TCSBRKP, (void *)(uintptr_t)__duration); +} + +static __inline__ int tcsetpgrp(int __fd, pid_t __p) +{ + return ioctl(__fd, TIOCSPGRP, &__p); +} + +static __inline__ speed_t cfgetospeed(const struct termios *__s) +{ + return (speed_t)(__s->c_cflag & CBAUD); +} + +static __inline__ speed_t cfgetispeed(const struct termios *__s) +{ + return (speed_t)(__s->c_cflag & CBAUD); +} + +static __inline__ int cfsetospeed(struct termios *__s, speed_t __v) +{ + __s->c_cflag = (__s->c_cflag & ~CBAUD) | (__v & CBAUD); + return 0; +} + +static __inline__ int cfsetispeed(struct termios *__s, speed_t __v) +{ + __s->c_cflag = (__s->c_cflag & ~CBAUD) | (__v & CBAUD); + return 0; +} + +#endif /* _TERMIOS_H */ diff --git a/klibc/klibc/include/time.h b/klibc/klibc/include/time.h new file mode 100644 index 0000000000..c69c231ec8 --- /dev/null +++ b/klibc/klibc/include/time.h @@ -0,0 +1,14 @@ +/* + * time.h + */ + +#ifndef _TIME_H +#define _TIME_H + +#include <klibc/extern.h> +#include <sys/time.h> + +__extern time_t time(time_t *); +__extern int nanosleep(const struct timespec *, struct timespec *); + +#endif /* _TIME_H */ diff --git a/klibc/klibc/include/unistd.h b/klibc/klibc/include/unistd.h new file mode 100644 index 0000000000..a9b434c16b --- /dev/null +++ b/klibc/klibc/include/unistd.h @@ -0,0 +1,111 @@ +/* + * unistd.h + */ + +#ifndef _UNISTD_H +#define _UNISTD_H + +#include <klibc/extern.h> +#include <klibc/compiler.h> +#include <stddef.h> +#include <sys/types.h> +#include <sys/select.h> + +__extern char **environ; +__extern __noreturn _exit(int); + +__extern pid_t fork(void); +__extern pid_t vfork(void); +__extern pid_t getpid(void); +__extern int setpgid(pid_t, pid_t); +__extern pid_t getppid(void); +__extern pid_t getpgrp(void); +__extern int setpgrp(void); +__extern pid_t setsid(void); +__extern pid_t getsid(pid_t); +__extern int execv(const char *, char * const *); +__extern int execvp(const char *, char * const *); +__extern int execve(const char *, char * const *, char * const *); +__extern int execvpe(const char *, char * const *, char * const *); +__extern int execl(const char *, const char *, ...); +__extern int execlp(const char *, const char *, ...); +__extern int execle(const char *, const char *, ...); +__extern int execlpe(const char *, const char *, ...); + +__extern int setuid(uid_t); +__extern uid_t getuid(void); +__extern int seteuid(uid_t); +__extern uid_t geteuid(void); +__extern int setgid(gid_t); +__extern gid_t getgid(void); +__extern int setegid(gid_t); +__extern gid_t getegid(void); +__extern int getgroups(int, gid_t *); +__extern int setgroups(size_t, const gid_t *); +__extern int setreuid(uid_t, uid_t); +__extern int setregid(gid_t, gid_t); +__extern int setresuid(uid_t, uid_t, uid_t); +__extern int setresgid(gid_t, gid_t, gid_t); +__extern int getfsuid(uid_t); +__extern int setfsuid(uid_t); + +__extern int access(const char *, int); +__extern int link(const char *, const char *); +__extern int unlink(const char *); +__extern int chdir(const char *); +__extern int chmod(const char *, mode_t); +__extern int mkdir(const char *, mode_t); +__extern int rmdir(const char *); +__extern int pipe(int *); +__extern int chroot(const char *); +__extern int symlink(const char *, const char *); +__extern int readlink(const char *, char *, size_t); +__extern int chown(const char *, uid_t, gid_t); +__extern int fchown(int, uid_t, gid_t); +__extern int lchown(const char *, uid_t, gid_t); +__extern char *getcwd(char *, size_t); + +__extern int sync(void); + +__extern ssize_t read(int, void *, size_t); +__extern ssize_t write(int, const void *, size_t); +#ifndef __IN_SYS_COMMON +__extern int open(const char *, int, ...); +#endif +__extern int close(int); +__extern off_t lseek(int, off_t, int); +__extern loff_t llseek(int, loff_t, int); +__extern int dup(int); +__extern int dup2(int, int); +__extern int fcntl(int, int, long); +__extern int ioctl(int, int, void *); +__extern int flock(int, int); +__extern int fsync(int); +__extern int fdatasync(int); + +__extern int pause(void); +__extern unsigned int alarm(unsigned int); +__extern unsigned int sleep(unsigned int); +__extern void usleep(unsigned long); + +__extern int gethostname(char *, size_t); +__extern int sethostname(const char *, size_t); +__extern int getdomainname(char *, size_t); +__extern int setdomainname(const char *, size_t); + +__extern void *__brk(void *); +__extern int brk(void *); +__extern void *sbrk(ptrdiff_t); + +__extern int getopt(int, char * const *, const char *); +__extern char *optarg; +__extern int optind, opterr, optopt; + +__extern int isatty(int); + +/* Standard file descriptor numbers. */ +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 + +#endif /* _UNISTD_H */ diff --git a/klibc/klibc/include/utime.h b/klibc/klibc/include/utime.h new file mode 100644 index 0000000000..3dfa03a14a --- /dev/null +++ b/klibc/klibc/include/utime.h @@ -0,0 +1,15 @@ +/* + * utime.h + */ + +#ifndef _UTIME_H +#define _UTIME_H + +#include <klibc/extern.h> +#include <sys/types.h> +#include <linux/utime.h> + +__extern int utime(const char *, const struct utimbuf *); + +#endif /* _UTIME_H */ + diff --git a/klibc/klibc/inet/bindresvport.c b/klibc/klibc/inet/bindresvport.c new file mode 100644 index 0000000000..b5f327bb33 --- /dev/null +++ b/klibc/klibc/inet/bindresvport.c @@ -0,0 +1,48 @@ +/* + * inet/bindresvport.c + */ + +#include <errno.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <string.h> +#include <unistd.h> + +#define START_PORT 600 +#define END_PORT (IPPORT_RESERVED - 1) +#define NUM_PORTS (END_PORT - START_PORT) + +int bindresvport(int sd, struct sockaddr_in *sin) +{ + struct sockaddr_in me; + static short port; + int ret = 0; + int i; + + if (sin == NULL) { + sin = &me; + memset(sin, 0, sizeof(me)); + sin->sin_port = AF_INET; + } + else if (sin->sin_family != AF_INET) { + errno = EPFNOSUPPORT; + ret = -1; + goto bail; + } + + if (port == 0) { + port = START_PORT + (getpid() % NUM_PORTS); + } + + for (i = 0; i < NUM_PORTS; i++, port++) { + sin->sin_port = htons(port); + if ((ret = bind(sd, sin, sizeof(*sin))) != -1) + break; + if (port == END_PORT) + port = START_PORT; + } + + bail: + return ret; +} diff --git a/klibc/klibc/inet/inet_addr.c b/klibc/klibc/inet/inet_addr.c new file mode 100644 index 0000000000..e04a4d0214 --- /dev/null +++ b/klibc/klibc/inet/inet_addr.c @@ -0,0 +1,14 @@ +/* + * inet/inet_addr.c + */ + +#include <arpa/inet.h> +#include <stdio.h> + +uint32_t inet_addr(const char *str) +{ + struct in_addr a; + int rv = inet_aton(str, &a); + + return rv ? INADDR_NONE : a.s_addr; +} diff --git a/klibc/klibc/inet/inet_aton.c b/klibc/klibc/inet/inet_aton.c new file mode 100644 index 0000000000..e581b492ad --- /dev/null +++ b/klibc/klibc/inet/inet_aton.c @@ -0,0 +1,23 @@ +/* + * inet/inet_aton.c + */ + +#include <arpa/inet.h> +#include <stdio.h> + +int inet_aton(const char *str, struct in_addr *addr) +{ + union { + uint8_t b[4]; + uint32_t l; + } a; + + if ( sscanf(str, "%hhu.%hhu.%hhu.%hhu", &a.b[0], &a.b[1], &a.b[2], &a.b[3]) == 4 ) { + addr->s_addr = a.l; /* Always in network byte order */ + return 1; + } else { + return 0; + } +} + + diff --git a/klibc/klibc/inet/inet_ntoa.c b/klibc/klibc/inet/inet_ntoa.c new file mode 100644 index 0000000000..5340aa622a --- /dev/null +++ b/klibc/klibc/inet/inet_ntoa.c @@ -0,0 +1,19 @@ +/* + * inet/inet_ntoa.c + */ + +#include <arpa/inet.h> +#include <stdio.h> + +char *inet_ntoa(struct in_addr addr) +{ + static char name[16]; + union { + uint8_t b[4]; + uint32_t l; + } a; + a.l = addr.s_addr; + + sprintf(name, "%u.%u.%u.%u", a.b[0], a.b[1], a.b[2], a.b[3]); + return name; +} diff --git a/klibc/klibc/inet/inet_ntop.c b/klibc/klibc/inet/inet_ntop.c new file mode 100644 index 0000000000..377bab7bf2 --- /dev/null +++ b/klibc/klibc/inet/inet_ntop.c @@ -0,0 +1,52 @@ +/* + * inet/inet_ntop.c + */ + +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <arpa/inet.h> +#include <netinet/in6.h> + +const char *inet_ntop(int af, const void *cp, char *buf, size_t len) +{ + size_t xlen; + + switch ( af ) { + case AF_INET: + { + union { + uint8_t b[4]; + uint32_t l; + } a; + a.l = ((const struct in_addr *)cp)->s_addr; + + xlen = snprintf(buf, len, "%u.%u.%u.%u", a.b[0], a.b[1], a.b[2], a.b[3]); + } + break; + + case AF_INET6: + { + const struct in6_addr *s = (const struct in6_addr *)cp; + + xlen = snprintf(buf, len, "%x:%x:%x:%x:%x:%x:%x:%x", + ntohs(s->s6_addr16[0]), ntohs(s->s6_addr16[1]), + ntohs(s->s6_addr16[2]), ntohs(s->s6_addr16[3]), + ntohs(s->s6_addr16[4]), ntohs(s->s6_addr16[5]), + ntohs(s->s6_addr16[6]), ntohs(s->s6_addr16[7])); + } + break; + + default: + errno = EAFNOSUPPORT; + return NULL; + } + + if ( xlen > len ) { + errno = ENOSPC; + return NULL; + } + + return buf; +} + diff --git a/klibc/klibc/inet/inet_pton.c b/klibc/klibc/inet/inet_pton.c new file mode 100644 index 0000000000..6c14b3cfb6 --- /dev/null +++ b/klibc/klibc/inet/inet_pton.c @@ -0,0 +1,74 @@ +/* + * inet/inet_pton.c + */ + +#include <stdio.h> +#include <stdint.h> +#include <errno.h> +#include <ctype.h> +#include <string.h> +#include <arpa/inet.h> +#include <netinet/in6.h> + +static inline int hexval(int ch) +{ + if ( ch >= '0' && ch <= '9' ) { + return ch-'0'; + } else if ( ch >= 'A' && ch <= 'F' ) { + return ch-'A'+10; + } else if ( ch >= 'a' && ch <= 'f' ) { + return ch-'a'+10; + } else { + return -1; + } +} + +int inet_pton(int af, const char *src, void *dst) +{ + switch ( af ) { + case AF_INET: + return inet_aton(src, (struct in_addr *)dst); + + case AF_INET6: + { + struct in6_addr *d = (struct in6_addr *)dst; + int colons = 0, dcolons = 0; + int i; + const char *p; + + /* A double colon will increment colons by 2, dcolons by 1 */ + for ( p = dst ; *p ; p++ ) { + if ( p[0] == ':' ) { + colons++; + if ( p[1] == ':' ) + dcolons++; + } else if ( !isxdigit(*p) ) + return 0; /* Not a valid address */ + } + + if ( colons > 7 || dcolons > 1 || (!dcolons && colons != 7) ) + return 0; /* Not a valid address */ + + memset(d, 0, sizeof(struct in6_addr)); + + i = 0; + for ( p = dst ; *p ; p++ ) { + if ( *p == ':' ) { + if ( p[1] == ':' ) { + i += (8-colons); + } else { + i++; + } + } else { + d->s6_addr16[i] = htons((ntohs(d->s6_addr16[i]) << 4) + hexval(*p)); + } + } + + return 1; + } + + default: + errno = EAFNOSUPPORT; + return -1; + } +} diff --git a/klibc/klibc/interp.S b/klibc/klibc/interp.S new file mode 100644 index 0000000000..303943697b --- /dev/null +++ b/klibc/klibc/interp.S @@ -0,0 +1,11 @@ +# +# This is a hack to generate the .intrp section, which then +# ld turns into an PT_INTERP header. +# + + .section ".interp","a" + .ascii LIBDIR + .ascii "/klibc-" + .ascii SOHASH + .ascii ".so" + .byte 0 diff --git a/klibc/klibc/isatty.c b/klibc/klibc/isatty.c new file mode 100644 index 0000000000..ff5e1ff748 --- /dev/null +++ b/klibc/klibc/isatty.c @@ -0,0 +1,21 @@ +/* + * isatty.c + */ + +#include <unistd.h> +#include <termios.h> +#include <errno.h> + +int isatty(int fd) +{ + int old_errno = errno; + int istty; + pid_t dummy; + + /* All ttys support TIOCGPGRP */ + istty = !ioctl(fd, TIOCGPGRP, &dummy); + errno = old_errno; + + return istty; +} + diff --git a/klibc/klibc/libgcc/__divdi3.c b/klibc/klibc/libgcc/__divdi3.c new file mode 100644 index 0000000000..be13caed7e --- /dev/null +++ b/klibc/klibc/libgcc/__divdi3.c @@ -0,0 +1,29 @@ +/* + * arch/i386/libgcc/__divdi3.c + */ + +#include <stdint.h> +#include <stddef.h> + +extern uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t *rem); + +int64_t __divdi3(int64_t num, int64_t den) +{ + int minus = 0; + int64_t v; + + if ( num < 0 ) { + num = -num; + minus = 1; + } + if ( den < 0 ) { + den = -den; + minus ^= 1; + } + + v = __udivmoddi4(num, den, NULL); + if ( minus ) + v = -v; + + return v; +} diff --git a/klibc/klibc/libgcc/__divsi3.c b/klibc/klibc/libgcc/__divsi3.c new file mode 100644 index 0000000000..24a7e044c8 --- /dev/null +++ b/klibc/klibc/libgcc/__divsi3.c @@ -0,0 +1,29 @@ +/* + * libgcc/__divsi3.c + */ + +#include <stdint.h> +#include <stddef.h> + +extern uint32_t __udivmodsi4(uint32_t num, uint32_t den, uint32_t *rem); + +int32_t __divsi3(int32_t num, int32_t den) +{ + int minus = 0; + int32_t v; + + if ( num < 0 ) { + num = -num; + minus = 1; + } + if ( den < 0 ) { + den = -den; + minus ^= 1; + } + + v = __udivmodsi4(num, den, NULL); + if ( minus ) + v = -v; + + return v; +} diff --git a/klibc/klibc/libgcc/__moddi3.c b/klibc/klibc/libgcc/__moddi3.c new file mode 100644 index 0000000000..3e613654e4 --- /dev/null +++ b/klibc/klibc/libgcc/__moddi3.c @@ -0,0 +1,29 @@ +/* + * arch/i386/libgcc/__moddi3.c + */ + +#include <stdint.h> +#include <stddef.h> + +extern uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t *rem); + +int64_t __moddi3(int64_t num, int64_t den) +{ + int minus = 0; + int64_t v; + + if ( num < 0 ) { + num = -num; + minus = 1; + } + if ( den < 0 ) { + den = -den; + minus ^= 1; + } + + (void) __udivmoddi4(num, den, &v); + if ( minus ) + v = -v; + + return v; +} diff --git a/klibc/klibc/libgcc/__modsi3.c b/klibc/klibc/libgcc/__modsi3.c new file mode 100644 index 0000000000..cf62b8b556 --- /dev/null +++ b/klibc/klibc/libgcc/__modsi3.c @@ -0,0 +1,29 @@ +/* + * libgcc/__modsi3.c + */ + +#include <stdint.h> +#include <stddef.h> + +extern uint32_t __udivmodsi4(uint32_t num, uint32_t den, uint32_t *rem); + +int32_t __modsi3(int32_t num, int32_t den) +{ + int minus = 0; + int32_t v; + + if ( num < 0 ) { + num = -num; + minus = 1; + } + if ( den < 0 ) { + den = -den; + minus ^= 1; + } + + (void) __udivmodsi4(num, den, &v); + if ( minus ) + v = -v; + + return v; +} diff --git a/klibc/klibc/libgcc/__udivdi3.c b/klibc/klibc/libgcc/__udivdi3.c new file mode 100644 index 0000000000..901ce2aea6 --- /dev/null +++ b/klibc/klibc/libgcc/__udivdi3.c @@ -0,0 +1,13 @@ +/* + * arch/i386/libgcc/__divdi3.c + */ + +#include <stdint.h> +#include <stddef.h> + +extern uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t *rem); + +uint64_t __udivdi3(uint64_t num, uint64_t den) +{ + return __udivmoddi4(num, den, NULL); +} diff --git a/klibc/klibc/libgcc/__udivmoddi4.c b/klibc/klibc/libgcc/__udivmoddi4.c new file mode 100644 index 0000000000..1c456543be --- /dev/null +++ b/klibc/klibc/libgcc/__udivmoddi4.c @@ -0,0 +1,32 @@ +#include <klibc/diverr.h> +#include <stdint.h> + +uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t *rem_p) +{ + uint64_t quot = 0, qbit = 1; + + if ( den == 0 ) { + __divide_error(); + return 0; /* If trap returns... */ + } + + /* Left-justify denominator and count shift */ + while ( (int64_t)den >= 0 ) { + den <<= 1; + qbit <<= 1; + } + + while ( qbit ) { + if ( den <= num ) { + num -= den; + quot += qbit; + } + den >>= 1; + qbit >>= 1; + } + + if ( rem_p ) + *rem_p = num; + + return quot; +} diff --git a/klibc/klibc/libgcc/__udivmodsi4.c b/klibc/klibc/libgcc/__udivmodsi4.c new file mode 100644 index 0000000000..61f6bef0a4 --- /dev/null +++ b/klibc/klibc/libgcc/__udivmodsi4.c @@ -0,0 +1,32 @@ +#include <klibc/diverr.h> +#include <stdint.h> + +uint32_t __udivmodsi4(uint32_t num, uint32_t den, uint32_t *rem_p) +{ + uint32_t quot = 0, qbit = 1; + + if ( den == 0 ) { + __divide_error(); + return 0; /* If trap returns... */ + } + + /* Left-justify denominator and count shift */ + while ( (int32_t)den >= 0 ) { + den <<= 1; + qbit <<= 1; + } + + while ( qbit ) { + if ( den <= num ) { + num -= den; + quot += qbit; + } + den >>= 1; + qbit >>= 1; + } + + if ( rem_p ) + *rem_p = num; + + return quot; +} diff --git a/klibc/klibc/libgcc/__udivsi3.c b/klibc/klibc/libgcc/__udivsi3.c new file mode 100644 index 0000000000..cba6f8f03d --- /dev/null +++ b/klibc/klibc/libgcc/__udivsi3.c @@ -0,0 +1,13 @@ +/* + * libgcc/__divsi3.c + */ + +#include <stdint.h> +#include <stddef.h> + +extern uint32_t __udivmodsi4(uint32_t num, uint32_t den, uint32_t *rem); + +uint32_t __udivsi3(uint32_t num, uint32_t den) +{ + return __udivmodsi4(num, den, NULL); +} diff --git a/klibc/klibc/libgcc/__umoddi3.c b/klibc/klibc/libgcc/__umoddi3.c new file mode 100644 index 0000000000..c007d4859f --- /dev/null +++ b/klibc/klibc/libgcc/__umoddi3.c @@ -0,0 +1,16 @@ +/* + * arch/i386/libgcc/__umoddi3.c + */ + +#include <stdint.h> +#include <stddef.h> + +extern uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t *rem); + +uint64_t __umoddi3(uint64_t num, uint64_t den) +{ + uint64_t v; + + (void) __udivmoddi4(num, den, &v); + return v; +} diff --git a/klibc/klibc/libgcc/__umodsi3.c b/klibc/klibc/libgcc/__umodsi3.c new file mode 100644 index 0000000000..e3db972c4e --- /dev/null +++ b/klibc/klibc/libgcc/__umodsi3.c @@ -0,0 +1,16 @@ +/* + * libgcc/__umodsi3.c + */ + +#include <stdint.h> +#include <stddef.h> + +extern uint32_t __udivmodsi4(uint32_t num, uint32_t den, uint32_t *rem); + +uint32_t __umodsi3(uint32_t num, uint32_t den) +{ + uint32_t v; + + (void) __udivmodsi4(num, den, &v); + return v; +} diff --git a/klibc/klibc/llseek.c b/klibc/klibc/llseek.c new file mode 100644 index 0000000000..fdffc16e2c --- /dev/null +++ b/klibc/klibc/llseek.c @@ -0,0 +1,34 @@ +/* + * llseek.c + * + * On 32-bit platforms, we need llseek() as well as lseek() to be + * able to handle large disks + */ + +#include <unistd.h> +#include <sys/syscall.h> + +#if BITSIZE == 32 + +static inline _syscall5(int, _llseek, int, fd, unsigned long, hi, unsigned long, lo, loff_t *,res, int, whence); + +loff_t llseek(int fd, loff_t offset, int whence) +{ + loff_t result; + int rv; + + rv = _llseek(fd, (unsigned long)(offset >> 32), + (unsigned long)offset, &result, whence); + + return rv ? (loff_t)-1 : result; +} + +#else + +loff_t llseek(int fd, loff_t offset, int whence) +{ + return lseek(fd, offset, whence); +} + +#endif + diff --git a/klibc/klibc/lrand48.c b/klibc/klibc/lrand48.c new file mode 100644 index 0000000000..4d05de2e89 --- /dev/null +++ b/klibc/klibc/lrand48.c @@ -0,0 +1,42 @@ +/* + * lrand48.c + */ + +#include <stdlib.h> +#include <stdint.h> + +unsigned short __rand48_seed[3]; + +long jrand48(unsigned short xsubi[3]) +{ + uint64_t x; + + /* The xsubi[] array is littleendian by spec */ + x = (uint64_t)xsubi[0] + + ((uint64_t)xsubi[1] << 16) + + ((uint64_t)xsubi[2] << 32); + + x = (0x5deece66dULL * x) + 0xb; + + xsubi[0] = (unsigned short)x; + xsubi[1] = (unsigned short)(x >> 16); + xsubi[2] = (unsigned short)(x >> 32); + + return (long)(int32_t)(x >> 16); +} + +long mrand48(void) +{ + return jrand48(__rand48_seed); +} + +long nrand48(unsigned short xsubi[3]) +{ + return (long)((uint32_t)jrand48(xsubi) >> 1); +} + +long lrand48(void) +{ + return (long)((uint32_t)(mrand48() >> 1)); +} + diff --git a/klibc/klibc/makeerrlist.pl b/klibc/klibc/makeerrlist.pl new file mode 100644 index 0000000000..121ed1f46b --- /dev/null +++ b/klibc/klibc/makeerrlist.pl @@ -0,0 +1,80 @@ +#!/usr/bin/perl +# +# This creates sys_errlist from <asm/errno.h> through somewhat +# heuristic matching. It presumes the relevant entries are of the form +# #define Exxxx <integer> /* comment */ +# + +use FileHandle; + +%errors = (); +%errmsg = (); +$maxerr = -1; +$rootdir = 'linux/include/'; # Must have trailing / + +sub parse_file($) { + my($file) = @_; + my($fh) = new FileHandle; + my($line, $error, $msg); + my($kernelonly) = 0; + + $file = $rootdir.$file; + + print STDERR "opening $file\n"; + + if ( !($fh->open("< ".$file)) ) { + die "$0: cannot open $file\n"; + } + + while ( defined($line = <$fh>) ) { + if ( $kernelonly ) { + if ( $line =~ /^\#\s*endif/ ) { + $kernelonly--; + } elsif ( $line =~ /^\#\sif/ ) { + $kernelonly++; + } + } else { + if ( $line =~ /^\#\s*define\s+([A-Z0-9_]+)\s+([0-9]+)\s*\/\*\s*(.*\S)\s*\*\// ) { + $error = $1; + $errno = $2+0; + $msg = $3; + print STDERR "$error ($errno) => \"$msg\"\n"; + $errors{$errno} = $error; + $errmsg{$errno} = $msg; + $maxerr = $errno if ( $errno > $maxerr ); + } elsif ( $line =~ /^\#\s*include\s+[\<\"](.*)[\>\"]/ ) { + parse_file($1); + } elsif ( $line =~ /^\#\s*ifdef\s+__KERNEL__/ ) { + $kernelonly++; + } + } + } + close($fh); + print STDERR "closing $file\n"; +} + +parse_file('linux/errno.h'); + +($type) = @ARGV; + +if ( $type eq '-errlist' ) { + print "#include <errno.h>\n"; + printf "const int sys_nerr = %d;\n", $maxerr+1; + printf "const char * const sys_errlist[%d] = {\n", $maxerr+1; + foreach $e ( sort(keys(%errors)) ) { + printf " [%s] = \"%s\",\n", $errors{$e}, $errmsg{$e}; + } + print "};\n"; +} elsif ( $type eq '-errnos' ) { + print "#include <errno.h>\n"; + printf "const int sys_nerr = %d;\n", $maxerr+1; + printf "const char * const sys_errlist[%d] = {\n", $maxerr+1; + foreach $e ( sort(keys(%errors)) ) { + printf " [%s] = \"%s\",\n", $errors{$e}, $errors{$e}; + } + print "};\n"; +} elsif ( $type eq '-maxerr' ) { + print $maxerr, "\n"; +} + + diff --git a/klibc/klibc/malloc.c b/klibc/klibc/malloc.c new file mode 100644 index 0000000000..20a2350d71 --- /dev/null +++ b/klibc/klibc/malloc.c @@ -0,0 +1,192 @@ +/* + * malloc.c + * + * Very simple linked-list based malloc()/free(). + */ + +#include <stdlib.h> +#include <sys/mman.h> +#include "malloc.h" + +struct free_arena_header __malloc_head = +{ + { + ARENA_TYPE_HEAD, + 0, + &__malloc_head, + &__malloc_head, + }, + &__malloc_head, + &__malloc_head +}; + +static void *__malloc_from_block(struct free_arena_header *fp, size_t size) +{ + size_t fsize; + struct free_arena_header *nfp, *na; + + fsize = fp->a.size; + + /* We need the 2* to account for the larger requirements of a free block */ + if ( fsize >= size+2*sizeof(struct arena_header) ) { + /* Bigger block than required -- split block */ + nfp = (struct free_arena_header *)((char *)fp + size); + na = fp->a.next; + + nfp->a.type = ARENA_TYPE_FREE; + nfp->a.size = fsize-size; + fp->a.type = ARENA_TYPE_USED; + fp->a.size = size; + + /* Insert into all-block chain */ + nfp->a.prev = fp; + nfp->a.next = na; + na->a.prev = nfp; + fp->a.next = nfp; + + /* Replace current block on free chain */ + nfp->next_free = fp->next_free; + nfp->prev_free = fp->prev_free; + fp->next_free->prev_free = nfp; + fp->prev_free->next_free = nfp; + } else { + /* Allocate the whole block */ + fp->a.type = ARENA_TYPE_USED; + + /* Remove from free chain */ + fp->next_free->prev_free = fp->prev_free; + fp->prev_free->next_free = fp->next_free; + } + + return (void *)(&fp->a + 1); +} + +static struct free_arena_header * +__free_block(struct free_arena_header *ah) +{ + struct free_arena_header *pah, *nah; + + pah = ah->a.prev; + nah = ah->a.next; + if ( pah->a.type == ARENA_TYPE_FREE && + (char *)pah+pah->a.size == (char *)ah ) { + /* Coalesce into the previous block */ + pah->a.size += ah->a.size; + pah->a.next = nah; + nah->a.prev = pah; + +#ifdef DEBUG_MALLOC + ah->a.type = ARENA_TYPE_DEAD; +#endif + + ah = pah; + pah = ah->a.prev; + } else { + /* Need to add this block to the free chain */ + ah->a.type = ARENA_TYPE_FREE; + + ah->next_free = __malloc_head.next_free; + ah->prev_free = &__malloc_head; + __malloc_head.next_free = ah; + ah->next_free->prev_free = ah; + } + + /* In either of the previous cases, we might be able to merge + with the subsequent block... */ + if ( nah->a.type == ARENA_TYPE_FREE && + (char *)ah+ah->a.size == (char *)nah ) { + ah->a.size += nah->a.size; + + /* Remove the old block from the chains */ + nah->next_free->prev_free = nah->prev_free; + nah->prev_free->next_free = nah->next_free; + ah->a.next = nah->a.next; + nah->a.next->a.prev = ah; + +#ifdef DEBUG_MALLOC + nah->a.type = ARENA_TYPE_DEAD; +#endif + } + + /* Return the block that contains the called block */ + return ah; +} + +void *malloc(size_t size) +{ + struct free_arena_header *fp; + struct free_arena_header *pah; + size_t fsize; + + if ( size == 0 ) + return NULL; + + /* Add the obligatory arena header, and round up */ + size = (size+2*sizeof(struct arena_header)-1) & ARENA_SIZE_MASK; + + for ( fp = __malloc_head.next_free ; fp->a.type != ARENA_TYPE_HEAD ; + fp = fp->next_free ) { + if ( fp->a.size >= size ) { + /* Found fit -- allocate out of this block */ + return __malloc_from_block(fp, size); + } + } + + /* Nothing found... need to request a block from the kernel */ + fsize = (size+MALLOC_CHUNK_MASK) & ~MALLOC_CHUNK_MASK; + fp = (struct free_arena_header *) + mmap(NULL, fsize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); + + if ( fp == (struct free_arena_header *)MAP_FAILED ) { + return NULL; /* Failed to get a block */ + } + + /* Insert the block into the management chains. We need to set + up the size and the main block list pointer, the rest of + the work is logically identical to free(). */ + fp->a.type = ARENA_TYPE_FREE; + fp->a.size = fsize; + + /* We need to insert this into the main block list in the proper + place -- this list is required to be sorted. Since we most likely + get memory assignments in ascending order, search backwards for + the proper place. */ + for ( pah = __malloc_head.a.prev ; pah->a.type != ARENA_TYPE_HEAD ; + pah = pah->a.prev ) { + if ( pah < fp ) + break; + } + + /* Now pah points to the node that should be the predecessor of + the new node */ + fp->a.next = pah->a.next; + fp->a.prev = pah; + pah->a.next = fp; + fp->a.next->a.prev = fp; + + + /* Insert into the free chain and coalesce with adjacent blocks */ + fp = __free_block(fp); + + /* Now we can allocate from this block */ + return __malloc_from_block(fp, size); +} + +void free(void *ptr) +{ + struct free_arena_header *ah; + + if ( !ptr ) + return; + + ah = (struct free_arena_header *) + ((struct arena_header *)ptr - 1); + +#ifdef DEBUG_MALLOC + assert( ah->a.type == ARENA_TYPE_USED ); +#endif + + __free_block(ah); + + /* Here we could insert code to return memory to the system. */ +} diff --git a/klibc/klibc/malloc.h b/klibc/klibc/malloc.h new file mode 100644 index 0000000000..e053f71401 --- /dev/null +++ b/klibc/klibc/malloc.h @@ -0,0 +1,51 @@ +/* + * malloc.h + * + * Internals for the memory allocator + */ + +#include <stdint.h> +#include <stddef.h> + +/* + * This is the minimum chunk size we will ask the kernel for; this should + * be a multiple of the page size on all architectures. + */ +#define MALLOC_CHUNK_SIZE 65536 +#define MALLOC_CHUNK_MASK (MALLOC_CHUNK_SIZE-1) + +/* + * This structure should be a power of two. This becomes the + * alignment unit. + */ +struct free_arena_header; + +struct arena_header { + size_t type; + size_t size; /* Also gives the location of the next entry */ + struct free_arena_header *next, *prev; +}; + +#ifdef DEBUG_MALLOC +#define ARENA_TYPE_USED 0x64e69c70 +#define ARENA_TYPE_FREE 0x012d610a +#define ARENA_TYPE_HEAD 0x971676b5 +#define ARENA_TYPE_DEAD 0xeeeeeeee +#else +#define ARENA_TYPE_USED 0 +#define ARENA_TYPE_FREE 1 +#define ARENA_TYPE_HEAD 2 +#endif + +#define ARENA_SIZE_MASK (~(sizeof(struct arena_header)-1)) + +/* + * This structure should be no more than twice the size of the + * previous structure. + */ +struct free_arena_header { + struct arena_header a; + struct free_arena_header *next_free, *prev_free; +}; + +extern struct free_arena_header __malloc_head; diff --git a/klibc/klibc/memccpy.c b/klibc/klibc/memccpy.c new file mode 100644 index 0000000000..22f68deaad --- /dev/null +++ b/klibc/klibc/memccpy.c @@ -0,0 +1,23 @@ +/* + * memccpy.c + * + * memccpy() + */ + +#include <stddef.h> +#include <string.h> + +void *memccpy(void *dst, const void *src, int c, size_t n) +{ + char *q = dst; + const char *p = src; + char ch; + + while ( n-- ) { + *q++ = ch = *p++; + if ( ch == (char)c ) + return q; + } + + return NULL; /* No instance of "c" found */ +} diff --git a/klibc/klibc/memchr.c b/klibc/klibc/memchr.c new file mode 100644 index 0000000000..c5c5fa2963 --- /dev/null +++ b/klibc/klibc/memchr.c @@ -0,0 +1,18 @@ +/* + * memchr.c + */ + +#include <stddef.h> +#include <string.h> + +void *memchr(const void *s, int c, size_t n) +{ + const unsigned char *sp = s; + + while ( n-- ) { + if ( *sp == (unsigned char)c ) + return (void *)sp; + } + + return NULL; +} diff --git a/klibc/klibc/memcmp.c b/klibc/klibc/memcmp.c new file mode 100644 index 0000000000..f6bc17286f --- /dev/null +++ b/klibc/klibc/memcmp.c @@ -0,0 +1,19 @@ +/* + * memcmp.c + */ + +#include <string.h> + +int memcmp(const void *s1, const void *s2, size_t n) +{ + const unsigned char *c1 = s1, *c2 = s2; + int d = 0; + + while ( n-- ) { + d = (int)*c1++ - (int)*c2++; + if ( d ) + break; + } + + return d; +} diff --git a/klibc/klibc/memcpy.c b/klibc/klibc/memcpy.c new file mode 100644 index 0000000000..b9171c300d --- /dev/null +++ b/klibc/klibc/memcpy.c @@ -0,0 +1,29 @@ +/* + * memcpy.c + */ + +#include <string.h> +#include <stdint.h> + +void *memcpy(void *dst, const void *src, size_t n) +{ + const char *p = src; + char *q = dst; +#if defined(__i386__) + size_t nl = n >> 2; + asm volatile("cld ; rep ; movsl ; movl %3,%0 ; rep ; movsb" + : "+c" (nl), "+S" (p), "+D" (q) + : "r" (n & 3)); +#elif defined(__x86_64__) + size_t nq = n >> 3; + asm volatile("cld ; rep ; movsq ; movl %3,%%ecx ; rep ; movsb" + : "+c" (nq), "+S" (p), "+D" (q) + : "r" ((uint32_t)(n & 7))); +#else + while ( n-- ) { + *q++ = *p++; + } +#endif + + return dst; +} diff --git a/klibc/klibc/memmem.c b/klibc/klibc/memmem.c new file mode 100644 index 0000000000..0f59938ffb --- /dev/null +++ b/klibc/klibc/memmem.c @@ -0,0 +1,44 @@ +/* + * memmem.c + * + * Find a byte string inside a longer byte string + * + * This uses the "Not So Naive" algorithm, a very simple but + * usually effective algorithm, see: + * + * http://www-igm.univ-mlv.fr/~lecroq/string/ + */ + +#include <string.h> + +void *memmem(const void *haystack, size_t n, const void *needle, size_t m) +{ + const unsigned char *y = (const unsigned char *)haystack; + const unsigned char *x = (const unsigned char *)needle; + + size_t j, k, l; + + if ( m > n ) + return NULL; + + if ( x[0] == x[1] ) { + k = 2; + l = 1; + } else { + k = 1; + l = 2; + } + + j = 0; + while ( j <= n-m ) { + if (x[1] != y[j+1]) { + j += k; + } else { + if ( !memcmp(x+2, y+j+2, m-2) && x[0] == y[j] ) + return (void *)&y[j]; + j += l; + } + } + + return NULL; +} diff --git a/klibc/klibc/memmove.c b/klibc/klibc/memmove.c new file mode 100644 index 0000000000..c1f042af39 --- /dev/null +++ b/klibc/klibc/memmove.c @@ -0,0 +1,34 @@ +/* + * memmove.c + */ + +#include <string.h> + +void *memmove(void *dst, const void *src, size_t n) +{ + const char *p = src; + char *q = dst; +#if defined(__i386__) || defined(__x86_64__) + if ( q < p ) { + asm volatile("cld ; rep ; movsb" : "+c" (n), "+S" (p), "+D" (q)); + } else { + p += (n-1); + q += (n-1); + asm volatile("std ; rep ; movsb" : "+c" (n), "+S" (p), "+D" (q)); + } +#else + if ( q < p ) { + while ( n-- ) { + *q++ = *p++; + } + } else { + p += n; + q += n; + while ( n-- ) { + *--q = *--p; + } + } +#endif + + return dst; +} diff --git a/klibc/klibc/memset.c b/klibc/klibc/memset.c new file mode 100644 index 0000000000..522cc59a1e --- /dev/null +++ b/klibc/klibc/memset.c @@ -0,0 +1,30 @@ +/* + * memset.c + */ + +#include <string.h> +#include <stdint.h> + +void *memset(void *dst, int c, size_t n) +{ + char *q = dst; + +#if defined(__i386__) + size_t nl = n >> 2; + asm volatile("cld ; rep ; stosl ; movl %3,%0 ; rep ; stosb" + : "+c" (nl), "+D" (q) + : "a" ((unsigned char)c * 0x01010101U), "r" (n & 3)); +#elif defined(__x86_64__) + size_t nq = n >> 3; + asm volatile("cld ; rep ; stosq ; movl %3,%%ecx ; rep ; stosb" + : "+c" (nq), "+D" (q) + : "a" ((unsigned char)c * 0x0101010101010101U), + "r" ((uint32_t)n & 7)); +#else + while ( n-- ) { + *q++ = c; + } +#endif + + return dst; +} diff --git a/klibc/klibc/memswap.c b/klibc/klibc/memswap.c new file mode 100644 index 0000000000..10440e3499 --- /dev/null +++ b/klibc/klibc/memswap.c @@ -0,0 +1,23 @@ +/* + * memswap() + * + * Swaps the contents of two nonoverlapping memory areas. + * This really could be done faster... + */ + +#include <string.h> + +void memswap(void *m1, void *m2, size_t n) +{ + char *p = m1; + char *q = m2; + char tmp; + + while ( n-- ) { + tmp = *p; + *p = *q; + *q = tmp; + + p++; q++; + } +} diff --git a/klibc/klibc/mmap.c b/klibc/klibc/mmap.c new file mode 100644 index 0000000000..3d28cba601 --- /dev/null +++ b/klibc/klibc/mmap.c @@ -0,0 +1,51 @@ +/* + * mmap.c + */ + +#include <stdint.h> +#include <errno.h> +#include <sys/syscall.h> +#include <sys/mman.h> +#include <asm/page.h> /* For PAGE_SHIFT */ + +#if defined(__sparc__) +# define MMAP2_SHIFT 12 /* Fixed by syscall definition */ +#else +# define MMAP2_SHIFT PAGE_SHIFT +#endif +#define MMAP2_MASK ((1UL << MMAP2_SHIFT)-1) + +/* + * Prefer mmap2() over mmap(), except on the architectures listed + */ + +#if defined(__NR_mmap2) && !defined(__sparc__) && !defined(__ia64__) + +/* This architecture uses mmap2() */ + +static inline _syscall6(void *,mmap2,void *,start,size_t,length,int,prot,int,flags,int,fd,off_t,offset); + +/* The Linux mmap2() system call takes a page offset as the offset argument. + We need to make sure we have the proper conversion in place. */ + +void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) +{ + if ( offset & MMAP2_MASK ) { + errno = EINVAL; + return MAP_FAILED; + } + + return mmap2(start, length, prot, flags, fd, (size_t)offset >> MMAP2_SHIFT); +} + +#else + +/* This architecture uses a plain mmap() system call */ +/* Only use this for architectures where mmap() is a real 6-argument system call! */ + +_syscall6(void *,mmap,void *,start,size_t,length,int,prot,int,flags,int,fd,off_t,offset) + +#endif + + + diff --git a/klibc/klibc/nice.c b/klibc/klibc/nice.c new file mode 100644 index 0000000000..f0d97a3cd0 --- /dev/null +++ b/klibc/klibc/nice.c @@ -0,0 +1,22 @@ +/* + * nice.c + */ + +#include <unistd.h> +#include <sched.h> +#include <sys/resource.h> +#include <sys/syscall.h> + +#ifdef __NR_nice + +_syscall1(int,nice,int,inc); + +#else + +int nice(int inc) +{ + pid_t me = getpid(); + return setpriority(me, PRIO_PROCESS, getpriority(me, PRIO_PROCESS)+inc); +} + +#endif diff --git a/klibc/klibc/onexit.c b/klibc/klibc/onexit.c new file mode 100644 index 0000000000..70a9c01f61 --- /dev/null +++ b/klibc/klibc/onexit.c @@ -0,0 +1,39 @@ +/* + * onexit.c + */ + +#include <stdlib.h> +#include <unistd.h> +#include "atexit.h" + +extern __noreturn (*__exit_handler)(int); +static struct atexit *__atexit_list; + +static __noreturn on_exit_exit(int rv) +{ + struct atexit *ap; + + for ( ap = __atexit_list ; ap ; ap = ap->next ) { + ap->fctn(rv, ap->arg); /* This assumes extra args are harmless */ + } + + _exit(rv); +} + +int on_exit(void (*fctn)(int, void *), void *arg) +{ + struct atexit *as = malloc(sizeof(struct atexit)); + + if ( !as ) + return -1; + + as->fctn = fctn; + as->arg = arg; + + as->next = __atexit_list; + __atexit_list = as; + + __exit_handler = on_exit_exit; + + return 0; +} diff --git a/klibc/klibc/pause.c b/klibc/klibc/pause.c new file mode 100644 index 0000000000..5748728472 --- /dev/null +++ b/klibc/klibc/pause.c @@ -0,0 +1,21 @@ +/* + * pause.c + */ + +#include <stddef.h> +#include <unistd.h> +#include <sys/time.h> +#include <sys/syscall.h> + +#ifdef __NR_pause + +_syscall0(int,pause); + +#else + +int pause(void) +{ + return select(0,NULL,NULL,NULL,NULL); +} + +#endif diff --git a/klibc/klibc/perror.c b/klibc/klibc/perror.c new file mode 100644 index 0000000000..45585cd577 --- /dev/null +++ b/klibc/klibc/perror.c @@ -0,0 +1,12 @@ +/* + * perror.c + */ + +#include <errno.h> +#include <stdio.h> +#include <string.h> + +void perror(const char *s) +{ + fprintf(stderr, "%s: error %d\n", s, errno); +} diff --git a/klibc/klibc/printf.c b/klibc/klibc/printf.c new file mode 100644 index 0000000000..34237592d6 --- /dev/null +++ b/klibc/klibc/printf.c @@ -0,0 +1,19 @@ +/* + * printf.c + */ + +#include <stdio.h> +#include <stdarg.h> + +#define BUFFER_SIZE 16384 + +int printf(const char *format, ...) +{ + va_list ap; + int rv; + + va_start(ap, format); + rv = vfprintf(stdout, format, ap); + va_end(ap); + return rv; +} diff --git a/klibc/klibc/pty.c b/klibc/klibc/pty.c new file mode 100644 index 0000000000..5907ca2ff5 --- /dev/null +++ b/klibc/klibc/pty.c @@ -0,0 +1,31 @@ +/* + * pty.c + * + * Basic Unix98 PTY functionality; assumes devpts + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <termios.h> +#include <sys/ioctl.h> + +char *ptsname(int fd) +{ + static char buffer[32]; /* Big enough to hold even a 64-bit pts no */ + unsigned int ptyno; + + if ( ioctl(fd, TIOCGPTN, &ptyno) ) + return NULL; + + snprintf(buffer, sizeof buffer, "/dev/pts/%u", ptyno); + + return buffer; +} + +int unlockpt(int fd) +{ + int unlock = 0; + + return ioctl(fd, TIOCSPTLCK, &unlock); +} diff --git a/klibc/klibc/puts.c b/klibc/klibc/puts.c new file mode 100644 index 0000000000..ecebf275da --- /dev/null +++ b/klibc/klibc/puts.c @@ -0,0 +1,13 @@ +/* + * puts.c + */ + +#include <stdio.h> + +int puts(const char *s) +{ + if ( fputs(s, stdout) < 0 ) + return -1; + + return _fwrite("\n", 1, stdout); +} diff --git a/klibc/klibc/qsort.c b/klibc/klibc/qsort.c new file mode 100644 index 0000000000..e2197ea2ae --- /dev/null +++ b/klibc/klibc/qsort.c @@ -0,0 +1,42 @@ +/* + * qsort.c + * + * This is actually combsort. It's an O(n log n) algorithm with + * simplicity/small code size being its main virtue. + */ + +#include <stddef.h> +#include <string.h> + +static inline size_t newgap(size_t gap) +{ + gap = (gap*10)/13; + if ( gap == 9 || gap == 10 ) + gap = 11; + + if ( gap < 1 ) + gap = 1; + return gap; +} + +void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) +{ + size_t gap = nmemb; + size_t i, j; + void *p1, *p2; + int swapped; + + do { + gap = newgap(gap); + swapped = 0; + + for ( i = 0, p1 = base ; i < nmemb-gap ; i++, (char *)p1 += size ) { + j = i+gap; + if ( compar(p1, p2 = (char *)base+j*size) > 0 ) { + memswap(p1, p2, size); + swapped = 1; + } + } + } while ( gap > 1 || swapped ); +} + diff --git a/klibc/klibc/raise.c b/klibc/klibc/raise.c new file mode 100644 index 0000000000..dcbb9c9c6c --- /dev/null +++ b/klibc/klibc/raise.c @@ -0,0 +1,11 @@ +/* + * raise.c + */ + +#include <unistd.h> +#include <signal.h> + +int raise(int signal) +{ + return kill(getpid(), signal); +} diff --git a/klibc/klibc/readdir.c b/klibc/klibc/readdir.c new file mode 100644 index 0000000000..bb216a1951 --- /dev/null +++ b/klibc/klibc/readdir.c @@ -0,0 +1,66 @@ +/* + * opendir/readdir/closedir + */ + +#include <unistd.h> +#include <fcntl.h> +#include <stdlib.h> +#include <sys/dirent.h> +#include <stdio.h> + +#define __IO_DIR_DEFINED +struct _IO_dir { + int fd; + size_t bytes_left; + struct dirent *next; + struct dirent buffer[15]; /* 15 times max dirent size =~ 4K */ +}; + +#include <dirent.h> + +DIR *opendir(const char *name) +{ + DIR *dp = malloc(sizeof(DIR)); + + if ( !dp ) + return NULL; + + dp->fd = open(name, O_DIRECTORY|O_RDONLY); + + if ( dp->fd < 0 ) { + free(dp); + return NULL; + } + + dp->bytes_left = 0; + + return dp; +} + +struct dirent *readdir(DIR *dir) +{ + struct dirent *dent; + int rv; + + if ( !dir->bytes_left ) { + rv = getdents(dir->fd, dir->buffer, sizeof(dir->buffer)); + if ( rv <= 0 ) + return NULL; + dir->bytes_left = rv; + dir->next = dir->buffer; + } + + dent = dir->next; + ((char *)dir->next) += dent->d_reclen; + dir->bytes_left -= dent->d_reclen; + + return dent; +} + +int closedir(DIR *dir) +{ + int rv; + rv = close(dir->fd); + free(dir); + return rv; +} diff --git a/klibc/klibc/realloc.c b/klibc/klibc/realloc.c new file mode 100644 index 0000000000..577c2001a5 --- /dev/null +++ b/klibc/klibc/realloc.c @@ -0,0 +1,49 @@ +/* + * realloc.c + */ + +#include <stdlib.h> +#include <string.h> + +#include "malloc.h" + +/* FIXME: This is cheesy, it should be fixed later */ + +void *realloc(void *ptr, size_t size) +{ + struct free_arena_header *ah; + void *newptr; + size_t oldsize; + + if ( !ptr ) + return malloc(size); + + if ( size == 0 ) { + free(ptr); + return NULL; + } + + /* Add the obligatory arena header, and round up */ + size = (size+2*sizeof(struct arena_header)-1) & ARENA_SIZE_MASK; + + ah = (struct free_arena_header *) + ((struct arena_header *)ptr - 1); + + if ( ah->a.size >= size && size >= (ah->a.size >> 2) ) { + /* This field is a good size already. */ + return ptr; + } else { + /* Make me a new block. This is kind of bogus; we should + be checking the adjacent blocks to see if we can do an + in-place adjustment... fix that later. */ + + oldsize = ah->a.size - sizeof(struct arena_header); + + newptr = malloc(size); + memcpy(newptr, ptr, (size < oldsize) ? size : oldsize); + free(ptr); + + return newptr; + } +} + diff --git a/klibc/klibc/reboot.c b/klibc/klibc/reboot.c new file mode 100644 index 0000000000..772c85910e --- /dev/null +++ b/klibc/klibc/reboot.c @@ -0,0 +1,15 @@ +/* + * reboot.c + */ + +#include <unistd.h> +#include <sys/reboot.h> +#include <sys/syscall.h> + +/* This provides the one-argument glibc-ish version of reboot. + The full four-argument system call is available as __reboot(). */ + +int reboot(int flag) +{ + return __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, flag, NULL); +} diff --git a/klibc/klibc/recv.c b/klibc/klibc/recv.c new file mode 100644 index 0000000000..4d30610cee --- /dev/null +++ b/klibc/klibc/recv.c @@ -0,0 +1,11 @@ +/* + * recv.c + */ + +#include <stddef.h> +#include <sys/socket.h> + +int recv(int s, void *buf, size_t len, unsigned int flags) +{ + return recvfrom(s, buf, len, flags, NULL, 0); +} diff --git a/klibc/klibc/sbrk.c b/klibc/klibc/sbrk.c new file mode 100644 index 0000000000..03ab3c14bb --- /dev/null +++ b/klibc/klibc/sbrk.c @@ -0,0 +1,23 @@ +/* sbrk.c - Change data segment size */ + +/* Written 2000 by Werner Almesberger */ + +#include <stddef.h> +#include <unistd.h> +#include <sys/types.h> + +char *__current_brk; /* Common with brk.c */ + +void *sbrk(ptrdiff_t increment) +{ + char *old_brk, *new_brk; + + if (!__current_brk) + __current_brk = __brk(NULL); + new_brk = __brk(__current_brk+increment); + if (new_brk != __current_brk+increment) + return (void *) -1; + old_brk = __current_brk; + __current_brk = new_brk; + return old_brk; +} diff --git a/klibc/klibc/seed48.c b/klibc/klibc/seed48.c new file mode 100644 index 0000000000..f8353c8715 --- /dev/null +++ b/klibc/klibc/seed48.c @@ -0,0 +1,19 @@ +/* + * seed48.c + */ + +#include <stdlib.h> +#include <stdint.h> +#include <string.h> + +extern unsigned short __rand48_seed[3]; + +unsigned short *seed48(const unsigned short xsubi[3]) +{ + static unsigned short oldseed[3]; + memcpy(oldseed, __rand48_seed, sizeof __rand48_seed); + memcpy(__rand48_seed, xsubi, sizeof __rand48_seed); + + return oldseed; +} + diff --git a/klibc/klibc/select.c b/klibc/klibc/select.c new file mode 100644 index 0000000000..2404bb1e64 --- /dev/null +++ b/klibc/klibc/select.c @@ -0,0 +1,9 @@ +#include <unistd.h> +#include <sys/syscall.h> + +#ifdef __NR__newselect +#undef __NR_select +#define __NR_select __NR__newselect +#endif + +_syscall5(int,select,int,a0,fd_set *,a1,fd_set *,a2,fd_set *,a3,struct timeval *,a4); diff --git a/klibc/klibc/send.c b/klibc/klibc/send.c new file mode 100644 index 0000000000..8c53d0f764 --- /dev/null +++ b/klibc/klibc/send.c @@ -0,0 +1,11 @@ +/* + * send.c + */ + +#include <stddef.h> +#include <sys/socket.h> + +int send(int s, const void *buf, size_t len, unsigned int flags) +{ + return sendto(s, buf, len, flags, NULL, 0); +} diff --git a/klibc/klibc/setegid.c b/klibc/klibc/setegid.c new file mode 100644 index 0000000000..09f2416e43 --- /dev/null +++ b/klibc/klibc/setegid.c @@ -0,0 +1,10 @@ +/* + * setegid.c + */ + +#include <unistd.h> + +int setegid(gid_t egid) +{ + return setregid(-1, egid); +} diff --git a/klibc/klibc/setenv.c b/klibc/klibc/setenv.c new file mode 100644 index 0000000000..d1118ff3ed --- /dev/null +++ b/klibc/klibc/setenv.c @@ -0,0 +1,124 @@ +/* + * setenv.c + */ + +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +/* Initialized to zero, meaning "not malloc'd" */ +static size_t __environ_size; + +/* str should be a duplicated version of the input string; + len is the length of the key including the = sign */ +static int _putenv(char *str, size_t len, int overwrite) +{ + char **p, *q; + char **newenv; + size_t n; + + n = 1; /* Include space for final NULL */ + for ( p = environ ; (q = *p) ; p++ ) { + n++; + if ( !strncmp(q,str,len) ) { + if ( overwrite ) + free(str); + else + *p = str; /* Memory leak... */ + return 0; + } + } + + /* Need to extend the environment */ + if ( n < __environ_size ) { + p[1] = NULL; + *p = str; + return 0; + } else { + if ( __environ_size ) { + newenv = realloc(environ, (__environ_size << 1)*sizeof(char *)); + if ( !newenv ) + return -1; + + __environ_size <<= 1; + } else { + /* Make a reasonable guess how much more space we need */ + size_t newsize = n+32; + newenv = malloc(newsize*sizeof(char *)); + if ( !newenv ) + return -1; + + memcpy(newenv, environ, n*sizeof(char *)); + __environ_size = newsize; + } + newenv[n+1] = NULL; + newenv[n] = str; + environ = newenv; + } + return 0; +} + +int putenv(const char *str) +{ + char *s; + const char *e, *z; + size_t len; + + if ( !str ) { + errno = EINVAL; + return -1; + } + + len = 0; e = NULL; + for ( z = str ; *z ; z++ ) { + len++; + if ( *z == '=' ) + e = z; + } + + if ( !e ) { + errno = EINVAL; + return -1; + } + + s = strdup(str); + if ( !s ) + return -1; + + return _putenv(s, len, 1); +} + +int setenv(const char *name, const char *val, int overwrite) +{ + const char *z; + char *s; + size_t l1, l2; + + if ( !name || !name[0] ) { + errno = EINVAL; + return -1; + } + + l1 = 0; + for ( z = name ; *z ; z++ ) { + l1++; + if ( *z == '=' ) { + errno = EINVAL; + return -1; + } + } + + l2 = strlen(val); + + s = malloc(l1+l2+2); + if ( !s ) + return -1; + + memcpy(s, name, l1); + s[l1] = '='; + memcpy(s+l1+1, val, l2); + s[l1+l2+1] = '\0'; + + return _putenv(s, l1+1, overwrite); +} diff --git a/klibc/klibc/seteuid.c b/klibc/klibc/seteuid.c new file mode 100644 index 0000000000..6d1ac3922a --- /dev/null +++ b/klibc/klibc/seteuid.c @@ -0,0 +1,10 @@ +/* + * seteuid.c + */ + +#include <unistd.h> + +int seteuid(uid_t euid) +{ + return setreuid(-1, euid); +} diff --git a/klibc/klibc/setpgrp.c b/klibc/klibc/setpgrp.c new file mode 100644 index 0000000000..001dd0435d --- /dev/null +++ b/klibc/klibc/setpgrp.c @@ -0,0 +1,10 @@ +/* + * setpgrp.c + */ + +#include <unistd.h> + +int setpgrp(void) +{ + return setpgid(0,0); +} diff --git a/klibc/klibc/setresgid.c b/klibc/klibc/setresgid.c new file mode 100644 index 0000000000..f1a8c6b45c --- /dev/null +++ b/klibc/klibc/setresgid.c @@ -0,0 +1,29 @@ +/* + * setresgid.c + */ + +#include <unistd.h> +#include <sys/syscall.h> + +#ifdef __NR_setresgid + +_syscall3(int,setresgid,gid_t,a0,gid_t,a1,gid_t,a2); + +#elif defined(__NR_setresgid32) + +static inline _syscall3(int,setresgid32,gid_t,a0,gid_t,a1,gid_t,a2); + +int setresgid(gid_t a0, gid_t a1, gid_t a2) +{ + if ( sizeof(gid_t) == sizeof(uint32_t) ) { + return setresgid32(a0,a1,a2); + } else { + uint32_t x0 = (a0 == (gid_t)-1) ? (uint32_t)-1 : a0; + uint32_t x1 = (a1 == (gid_t)-1) ? (uint32_t)-1 : a1; + uint32_t x2 = (a2 == (gid_t)-1) ? (uint32_t)-1 : a2; + + return setresgid32(x0,x1,x2); + } +} + +#endif diff --git a/klibc/klibc/setresuid.c b/klibc/klibc/setresuid.c new file mode 100644 index 0000000000..a587acbae3 --- /dev/null +++ b/klibc/klibc/setresuid.c @@ -0,0 +1,30 @@ +/* + * setresuid.c + */ + +#include <unistd.h> +#include <sys/syscall.h> + +#ifdef __NR_setresuid + +_syscall3(int,setresuid,uid_t,a0,uid_t,a1,uid_t,a2); + +#elif defined(__NR_setresuid32) + +static inline _syscall3(int,setresuid32,uid_t,a0,uid_t,a1,uid_t,a2); + +int setresuid(uid_t a0, uid_t a1, uid_t a2) +{ + if ( sizeof(uid_t) == sizeof(uint32_t) ) { + return setresuid32(a0,a1,a2); + } else { + uint32_t x0 = (a0 == (uid_t)-1) ? (uint32_t)-1 : a0; + uint32_t x1 = (a1 == (uid_t)-1) ? (uint32_t)-1 : a1; + uint32_t x2 = (a2 == (uid_t)-1) ? (uint32_t)-1 : a2; + + return setresuid32(x0,x1,x2); + } +} + +#endif + diff --git a/klibc/klibc/sha1hash.c b/klibc/klibc/sha1hash.c new file mode 100644 index 0000000000..600d51248c --- /dev/null +++ b/klibc/klibc/sha1hash.c @@ -0,0 +1,317 @@ +/* +SHA-1 in C +By Steve Reid <sreid@sea-to-sky.net> +100% Public Domain + +----------------- +Modified 7/98 +By James H. Brown <jbrown@burgoyne.com> +Still 100% Public Domain + +Corrected a problem which generated improper hash values on 16 bit machines +Routine SHA1Update changed from + void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int +len) +to + void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned +long len) + +The 'len' parameter was declared an int which works fine on 32 bit machines. +However, on 16 bit machines an int is too small for the shifts being done +against +it. This caused the hash function to generate incorrect values if len was +greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update(). + +Since the file IO in main() reads 16K at a time, any file 8K or larger would +be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million +"a"s). + +I also changed the declaration of variables i & j in SHA1Update to +unsigned long from unsigned int for the same reason. + +These changes should make no difference to any 32 bit implementations since +an +int and a long are the same size in those environments. + +-- +I also corrected a few compiler warnings generated by Borland C. +1. Added #include <process.h> for exit() prototype +2. Removed unused variable 'j' in SHA1Final +3. Changed exit(0) to return(0) at end of main. + +ALL changes I made can be located by searching for comments containing 'JHB' +----------------- +Modified 8/98 +By Steve Reid <sreid@sea-to-sky.net> +Still 100% public domain + +1- Removed #include <process.h> and used return() instead of exit() +2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall) +3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net + +----------------- +Modified 4/01 +By Saul Kravitz <Saul.Kravitz@celera.com> +Still 100% PD +Modified to run on Compaq Alpha hardware. + +----------------- +Modified 2/03 +By H. Peter Anvin <hpa@zytor.com> +Still 100% PD +Modified to run on any hardware with <inttypes.h> and <netinet/in.h> +Changed the driver program + +*/ + +/* +Test Vectors (from FIPS PUB 180-1) +"abc" + A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D +"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 +A million repetitions of "a" + 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F +*/ + +/* #define SHA1HANDSOFF */ + +#include <stdio.h> +#include <string.h> +#include <inttypes.h> +#include <netinet/in.h> /* For htonl/ntohl/htons/ntohs */ + +/* #include <process.h> */ /* prototype for exit() - JHB */ +/* Using return() instead of exit() - SWR */ + +typedef struct { + uint32_t state[5]; + uint32_t count[2]; + unsigned char buffer[64]; +} SHA1_CTX; + +void SHA1Transform(uint32_t state[5], unsigned char buffer[64]); +void SHA1Init(SHA1_CTX* context); +void SHA1Update(SHA1_CTX* context, unsigned char* data, uint32_t len); /* +JHB */ +void SHA1Final(unsigned char digest[20], SHA1_CTX* context); + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +#define blk0(i) (block->l[i] = ntohl(block->l[i])) +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + + +#ifdef VERBOSE /* SAK */ +void SHAPrintContext(SHA1_CTX *context, char *msg){ + printf("%s (%d,%d) %x %x %x %x %x\n", + msg, + context->count[0], context->count[1], + context->state[0], + context->state[1], + context->state[2], + context->state[3], + context->state[4]); +} +#endif + +/* Hash a single 512-bit block. This is the core of the algorithm. */ + +void SHA1Transform(uint32_t state[5], unsigned char buffer[64]) +{ +uint32_t a, b, c, d, e; +typedef union { + unsigned char c[64]; + uint32_t l[16]; +} CHAR64LONG16; +CHAR64LONG16* block; +#ifdef SHA1HANDSOFF +static unsigned char workspace[64]; + block = (CHAR64LONG16*)workspace; + memcpy(block, buffer, 64); +#else + block = (CHAR64LONG16*)buffer; +#endif + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; +} + + +/* SHA1Init - Initialize new context */ + +void SHA1Init(SHA1_CTX* context) +{ + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + + +/* Run your data through this. */ + +void SHA1Update(SHA1_CTX* context, unsigned char* data, uint32_t len) /* +JHB */ +{ +uint32_t i, j; /* JHB */ + +#ifdef VERBOSE + SHAPrintContext(context, "before"); +#endif + j = (context->count[0] >> 3) & 63; + if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; + context->count[1] += (len >> 29); + if ((j + len) > 63) { + memcpy(&context->buffer[j], data, (i = 64-j)); + SHA1Transform(context->state, context->buffer); + for ( ; i + 63 < len; i += 64) { + SHA1Transform(context->state, &data[i]); + } + j = 0; + } + else i = 0; + memcpy(&context->buffer[j], &data[i], len - i); +#ifdef VERBOSE + SHAPrintContext(context, "after "); +#endif +} + + +/* Add padding and return the message digest. */ + +void SHA1Final(unsigned char digest[20], SHA1_CTX* context) +{ +uint32_t i; /* JHB */ +unsigned char finalcount[8]; + + for (i = 0; i < 8; i++) { + finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] + >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ + } + SHA1Update(context, (unsigned char *)"\200", 1); + while ((context->count[0] & 504) != 448) { + SHA1Update(context, (unsigned char *)"\0", 1); + } + SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() +*/ + for (i = 0; i < 20; i++) { + digest[i] = (unsigned char) + ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); + } + /* Wipe variables */ + i = 0; /* JHB */ + memset(context->buffer, 0, 64); + memset(context->state, 0, 20); + memset(context->count, 0, 8); + memset(finalcount, 0, 8); /* SWR */ +#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */ + SHA1Transform(context->state, context->buffer); +#endif +} + +/*************************************************************/ + +/* This is not quite the MIME base64 algorithm: it uses _ instead of /, + and instead of padding the output with = characters we just make the + output shorter. */ +char *mybase64(uint8_t digest[20]) +{ + static const char charz[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_"; + uint8_t input[21]; + static char output[28]; + int i, j; + uint8_t *p; + char *q; + uint32_t bv; + + memcpy(input, digest, 20); + input[20] = 0; /* Pad to multiple of 3 bytes */ + + p = input; q = output; + for ( i = 0 ; i < 7 ; i++ ) { + bv = (p[0] << 16) | (p[1] << 8) | p[2]; + p += 3; + for ( j = 0 ; j < 4 ; j++ ) { + *q++ = charz[(bv >> 18) & 0x3f]; + bv <<= 6; + } + } + *--q = '\0'; /* The last character is not significant */ + return output; +} + +int main(int argc, char** argv) +{ + int i, j; + SHA1_CTX context; + uint8_t digest[20], buffer[16384]; + FILE* file; + + if (argc < 2) { + file = stdin; + } + else { + if (!(file = fopen(argv[1], "rb"))) { + fputs("Unable to open file.", stderr); + return(-1); + } + } + SHA1Init(&context); + while (!feof(file)) { /* note: what if ferror(file) */ + i = fread(buffer, 1, 16384, file); + SHA1Update(&context, buffer, i); + } + SHA1Final(digest, &context); + fclose(file); + + puts(mybase64(digest)); + + return 0; +} diff --git a/klibc/klibc/sigaction.c b/klibc/klibc/sigaction.c new file mode 100644 index 0000000000..ebd34710f1 --- /dev/null +++ b/klibc/klibc/sigaction.c @@ -0,0 +1,19 @@ +/* + * sigaction.c + */ + +#include <signal.h> +#include <sys/syscall.h> + +#ifdef __NR_sigaction + +_syscall3(int,sigaction,int,sig,const struct sigaction *,act,struct sigaction *,oact); + +#else + +int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) +{ + return rt_sigaction(sig, act, oact, sizeof(sigset_t)); +} + +#endif diff --git a/klibc/klibc/siglist.c b/klibc/klibc/siglist.c new file mode 100644 index 0000000000..dce7355079 --- /dev/null +++ b/klibc/klibc/siglist.c @@ -0,0 +1,115 @@ +/* + * siglist.h + * + * Construct the signal list + */ + +#include <signal.h> +#include <unistd.h> + +const char * const sys_siglist[NSIG] = { +#ifdef SIGABRT + [SIGABRT] = "Aborted", +#endif +#ifdef SIGALRM + [SIGALRM] = "Alarm clock", +#endif +#ifdef SIGBUS + [SIGBUS] = "Bus error", +#endif +#ifdef SIGCHLD + [SIGCHLD] = "Child exited", +#endif +#if defined(SIGCLD) && (SIGCHLD != SIGCLD) + [SIGCLD] = "Child exited", +#endif +#ifdef SIGEMT + [SIGEMT] = "Emulation trap", +#endif +#ifdef SIGFPE + [SIGFPE] = "Floating point exception", +#endif +#ifdef SIGHUP + [SIGHUP] = "Hangup", +#endif +#ifdef SIGILL + [SIGILL] = "Illegal instruction", +#endif + /* SIGINFO == SIGPWR */ +#ifdef SIGINT + [SIGINT] = "Interrupt", +#endif +#ifdef SIGIO + [SIGIO] = "I/O possible", +#endif +#if defined(SIGIOT) && (SIGIOT != SIGABRT) + [SIGIOT] = "I/O trap", +#endif +#ifdef SIGKILL + [SIGKILL] = "Killed", +#endif +#if defined(SIGLOST) && (SIGLOST != SIGIO) && (SIGLOST != SIGPWR) + [SIGLOST] = "Lock lost", +#endif +#ifdef SIGPIPE + [SIGPIPE] = "Broken pipe", +#endif +#if defined(SIGPOLL) && (SIGPOLL != SIGIO) + [SIGPOLL] = "Pollable event", +#endif +#ifdef SIGPROF + [SIGPROF] = "Profiling timer expired", +#endif +#ifdef SIGPWR + [SIGPWR] = "Power failure", +#endif +#ifdef SIGQUIT + [SIGQUIT] = "Quit", +#endif + /* SIGRESERVE == SIGUNUSED */ +#ifdef SIGSEGV + [SIGSEGV] = "Segment violation", +#endif +#ifdef SIGSTKFLT + [SIGSTKFLT] = "Stack fault", +#endif +#ifdef SIGSTOP + [SIGSTOP] = "Stopped (signal)", +#endif +#ifdef SIGSYS + [SIGSYS] = "Bad system call", +#endif +#ifdef SIGTERM + [SIGTERM] = "Terminated", +#endif +#ifdef SIGTSTP + [SIGTSTP] = "Stopped", +#endif +#ifdef SIGTTIN + [SIGTTIN] = "Stopped (tty input)", +#endif +#ifdef SIGTTOU + [SIGTTOU] = "Stopped (tty output)", +#endif +#ifdef SIGURG + [SIGURG] = "Urgent I/O condition", +#endif +#ifdef SIGUSR1 + [SIGUSR1] = "User signal 1", +#endif +#ifdef SIGUSR2 + [SIGUSR2] = "User signal 2", +#endif +#ifdef SIGVTALRM + [SIGVTALRM] = "Virtual timer expired", +#endif +#ifdef SIGWINCH + [SIGWINCH] = "Window size changed", +#endif +#ifdef SIGXCPU + [SIGXCPU] = "CPU time limit exceeded", +#endif +#ifdef SIGXFSZ + [SIGXFSZ] = "File size limit exceeded", +#endif +}; diff --git a/klibc/klibc/siglongjmp.c b/klibc/klibc/siglongjmp.c new file mode 100644 index 0000000000..2ba1239b6b --- /dev/null +++ b/klibc/klibc/siglongjmp.c @@ -0,0 +1,16 @@ +/* + * siglongjmp.c + * + * sigsetjmp() is a macro, by necessity (it's either that or write + * it in assembly), but siglongjmp() is a normal function. + */ + +#include <setjmp.h> +#include <signal.h> + +__noreturn siglongjmp(sigjmp_buf buf, int retval) +{ + sigprocmask(SIG_SETMASK, &buf->__sigs, NULL); + longjmp(buf->__jmpbuf, retval); +} + diff --git a/klibc/klibc/signal.c b/klibc/klibc/signal.c new file mode 100644 index 0000000000..982d0c659d --- /dev/null +++ b/klibc/klibc/signal.c @@ -0,0 +1,11 @@ +/* + * signal.c + */ + +#include <signal.h> + +__sighandler_t signal(int signum, __sighandler_t handler) +{ + /* Linux/SysV signal() semantics */ + return __signal(signum, handler, SA_RESETHAND); +} diff --git a/klibc/klibc/sigpending.c b/klibc/klibc/sigpending.c new file mode 100644 index 0000000000..afbcf3cf34 --- /dev/null +++ b/klibc/klibc/sigpending.c @@ -0,0 +1,19 @@ +/* + * sigpending.c + */ + +#include <signal.h> +#include <sys/syscall.h> + +#ifdef __NR_sigpending + +_syscall1(int,sigpending,sigset_t *,set); + +#else + +int sigpending(sigset_t *set) +{ + return rt_sigpending(set, sizeof(sigset_t)); +} + +#endif diff --git a/klibc/klibc/sigprocmask.c b/klibc/klibc/sigprocmask.c new file mode 100644 index 0000000000..3a90f67732 --- /dev/null +++ b/klibc/klibc/sigprocmask.c @@ -0,0 +1,19 @@ +/* + * sigprocmask.c + */ + +#include <signal.h> +#include <sys/syscall.h> + +#ifdef __NR_sigprocmask + +_syscall3(int,sigprocmask,int,how,const sigset_t *,set,sigset_t *,oset); + +#else + +int sigprocmask(int how, const sigset_t *set, sigset_t *oset) +{ + return rt_sigprocmask(how, set, oset, sizeof(sigset_t)); +} + +#endif diff --git a/klibc/klibc/sigsuspend.c b/klibc/klibc/sigsuspend.c new file mode 100644 index 0000000000..85cdea20ca --- /dev/null +++ b/klibc/klibc/sigsuspend.c @@ -0,0 +1,19 @@ +/* + * sigsuspend.c + */ + +#include <signal.h> +#include <sys/syscall.h> + +#ifdef __NR_sigsuspend + +_syscall1(int,sigsuspend,const sigset_t *,mask); + +#else + +int sigsuspend(const sigset_t *mask) +{ + return rt_sigsuspend(mask, sizeof *mask); +} + +#endif diff --git a/klibc/klibc/sleep.c b/klibc/klibc/sleep.c new file mode 100644 index 0000000000..eb3777e8a6 --- /dev/null +++ b/klibc/klibc/sleep.c @@ -0,0 +1,20 @@ +/* + * sleep.c + */ + +#include <errno.h> +#include <time.h> + +unsigned int sleep(unsigned int seconds) +{ + struct timespec ts; + + ts.tv_sec = seconds; + ts.tv_nsec = 0; + if ( !nanosleep(&ts,&ts) ) + return 0; + else if ( errno == EINTR ) + return ts.tv_sec; + else + return -1; +} diff --git a/klibc/klibc/snprintf.c b/klibc/klibc/snprintf.c new file mode 100644 index 0000000000..c642851b2f --- /dev/null +++ b/klibc/klibc/snprintf.c @@ -0,0 +1,16 @@ +/* + * snprintf.c + */ + +#include <stdio.h> + +int snprintf(char *buffer, size_t n, const char *format, ...) +{ + va_list ap; + int rv; + + va_start(ap, format); + rv = vsnprintf(buffer, n, format, ap); + va_end(ap); + return rv; +} diff --git a/klibc/klibc/socketcalls.pl b/klibc/klibc/socketcalls.pl new file mode 100644 index 0000000000..cf4daf6036 --- /dev/null +++ b/klibc/klibc/socketcalls.pl @@ -0,0 +1,71 @@ +#!/usr/bin/perl +($arch, $file) = @ARGV; + +if (!open(FILE, "< $file")) { + print STDERR "$file: $!\n"; + exit(1); +} + +while ( defined($line = <FILE>) ) { + chomp $line; + $line =~ s/\s*\#.*$//; # Strip comments and trailing blanks + next unless $line; + + if ( $line =~ /^\s*(.*)\s+([_a-zA-Z][_a-zA-Z0-9]+)\s*\((.*)\)$/ ) { + $type = $1; + $name = $2; + $argv = $3; + + @args = split(/\s*\,\s*/, $argv); + @cargs = (); + + $i = 0; + for $arg ( @args ) { + push(@cargs, "$arg a".$i++); + } + $nargs = $i; + + if ( $arch eq 'i386' ) { + open(OUT, "> socketcalls/${name}.S") + or die "$0: Cannot open socketcalls/${name}.S\n"; + + print OUT "#include <sys/socketcalls.h>\n"; + print OUT "\n"; + print OUT "\t.text\n"; + print OUT "\t.align 4\n"; + print OUT "\t.globl ${name}\n"; + print OUT "\t.type ${name},\@function\n"; + print OUT "${name}:\n"; + print OUT "\tmovb \$SYS_\U${name}\E,%al\n"; + print OUT "\tjmp __socketcall_common\n"; + print OUT "\t.size ${name},.-${name}\n"; + } else { + open(OUT, "> socketcalls/${name}.c") + or die "$0: Cannot open socketcalls/${name}.c\n"; + print OUT "#include \"socketcommon.h\"\n\n"; + + print OUT "#ifdef __NR_$name\n\n"; + print OUT "_syscall", scalar(@args), "(", $type, ',', $name; + $i = 0; + foreach $arg ( @args ) { + print OUT ",", $arg, ",a",$i++; + } + print OUT ");\n"; + print OUT "\n#else\n\n"; + + print OUT "$type $name (", join(', ', @cargs), ")\n"; + print OUT "{\n"; + print OUT " unsigned long args[$nargs];\n"; + for ( $i = 0 ; $i < $nargs ; $i++ ) { + print OUT " args[$i] = (unsigned long)a$i;\n"; + } + print OUT " return ($type) socketcall(SYS_\U${name}\E, args);\n"; + print OUT "}\n"; + print OUT "\n#endif\n"; + } + close(OUT); + } else { + print STDERR "$file:$.: Could not parse input\n"; + exit(1); + } +} diff --git a/klibc/klibc/socketcommon.h b/klibc/klibc/socketcommon.h new file mode 100644 index 0000000000..7a5acaadaf --- /dev/null +++ b/klibc/klibc/socketcommon.h @@ -0,0 +1,25 @@ +/* + * socketcommon.h + * + * Common header file for socketcall stubs + */ + +#define __IN_SYS_COMMON +#include <errno.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/syscall.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <linux/net.h> + +/* + * Some architectures have socketcall(), some have real syscalls, + * and some have both, but the syscall version is always preferred. + * Look for __NR_<call> to probe for the existence of a syscall. + */ + +#ifdef __NR_socketcall +static inline _syscall2(int,socketcall,int,call,unsigned long *,args); +#endif diff --git a/klibc/klibc/sprintf.c b/klibc/klibc/sprintf.c new file mode 100644 index 0000000000..31f28af005 --- /dev/null +++ b/klibc/klibc/sprintf.c @@ -0,0 +1,18 @@ +/* + * sprintf.c + */ + +#include <stdio.h> +#include <unistd.h> + +int sprintf(char *buffer, const char *format, ...) +{ + va_list ap; + int rv; + + va_start(ap, format); + rv = vsnprintf(buffer, ~(size_t)0, format, ap); + va_end(ap); + + return rv; +} diff --git a/klibc/klibc/srand48.c b/klibc/klibc/srand48.c new file mode 100644 index 0000000000..a3df16d95c --- /dev/null +++ b/klibc/klibc/srand48.c @@ -0,0 +1,16 @@ +/* + * srand48.c + */ + +#include <stdlib.h> +#include <stdint.h> + +extern unsigned short __rand48_seed[3]; + + +void srand48(long seedval) +{ + __rand48_seed[0] = 0x330e; + __rand48_seed[1] = (unsigned short)seedval; + __rand48_seed[2] = (unsigned short)((uint32_t)seedval >> 16); +} diff --git a/klibc/klibc/sscanf.c b/klibc/klibc/sscanf.c new file mode 100644 index 0000000000..81aab9e05b --- /dev/null +++ b/klibc/klibc/sscanf.c @@ -0,0 +1,17 @@ +/* + * sscanf() + */ + +#include <stdio.h> + +int sscanf(const char *str, const char *format, ...) +{ + va_list ap; + int rv; + + va_start(ap, format); + rv = vsscanf(str, format, ap); + va_end(ap); + + return rv; +} diff --git a/klibc/klibc/strcat.c b/klibc/klibc/strcat.c new file mode 100644 index 0000000000..a5f9477866 --- /dev/null +++ b/klibc/klibc/strcat.c @@ -0,0 +1,11 @@ +/* + * strcat.c + */ + +#include <string.h> + +char *strcat(char *dst, const char *src) +{ + strcpy(strchr(dst, '\0'), src); + return dst; +} diff --git a/klibc/klibc/strchr.c b/klibc/klibc/strchr.c new file mode 100644 index 0000000000..192f83600c --- /dev/null +++ b/klibc/klibc/strchr.c @@ -0,0 +1,16 @@ +/* + * strchr.c + */ + +#include <string.h> + +char *strchr(const char *s, int c) +{ + while ( *s != (char)c ) { + if ( ! *s ) + return NULL; + s++; + } + + return (char *)s; +} diff --git a/klibc/klibc/strcmp.c b/klibc/klibc/strcmp.c new file mode 100644 index 0000000000..f44774f443 --- /dev/null +++ b/klibc/klibc/strcmp.c @@ -0,0 +1,20 @@ +/* + * strcmp.c + */ + +#include <string.h> + +int strcmp(const char *s1, const char *s2) +{ + const unsigned char *c1 = s1, *c2 = s2; + unsigned char ch; + int d = 0; + + while ( 1 ) { + d = (int)(ch = *c1++) - (int)*c2++; + if ( d || !ch ) + break; + } + + return d; +} diff --git a/klibc/klibc/strcpy.c b/klibc/klibc/strcpy.c new file mode 100644 index 0000000000..8372eba50b --- /dev/null +++ b/klibc/klibc/strcpy.c @@ -0,0 +1,20 @@ +/* + * strcpy.c + * + * strcpy() + */ + +#include <string.h> + +char *strcpy(char *dst, const char *src) +{ + char *q = dst; + const char *p = src; + char ch; + + do { + *q++ = ch = *p++; + } while ( ch ); + + return dst; +} diff --git a/klibc/klibc/strdup.c b/klibc/klibc/strdup.c new file mode 100644 index 0000000000..eb170c2645 --- /dev/null +++ b/klibc/klibc/strdup.c @@ -0,0 +1,17 @@ +/* + * strdup.c + */ + +#include <string.h> +#include <stdlib.h> + +char *strdup(const char *s) +{ + int l = strlen(s)+1; + char *d = malloc(l); + + if ( d ) + memcpy(d, s, l); + + return d; +} diff --git a/klibc/klibc/strerror.c b/klibc/klibc/strerror.c new file mode 100644 index 0000000000..754a30693c --- /dev/null +++ b/klibc/klibc/strerror.c @@ -0,0 +1,25 @@ +/* + * strerror.c + */ + +#include <string.h> + +char *strerror(int errnum) +{ + static char message[32] = "error "; /* enough for error 2^63-1 */ + + char numbuf[32]; + char *p; + int len; + + p = numbuf+sizeof numbuf; + *--p = '\0'; + + do { + *--p = (errnum % 10) + '0'; + errnum /= 10; + } while ( errnum ); + + return (char *)memcpy(message+6, p, (numbuf+sizeof numbuf)-p); +} + diff --git a/klibc/klibc/strlen.c b/klibc/klibc/strlen.c new file mode 100644 index 0000000000..4d773f9a05 --- /dev/null +++ b/klibc/klibc/strlen.c @@ -0,0 +1,14 @@ +/* + * strlen() + */ + +#include <string.h> + +size_t strlen(const char *s) +{ + const char *ss = s; + while ( *ss ) + ss++; + return ss-s; +} + diff --git a/klibc/klibc/strncat.c b/klibc/klibc/strncat.c new file mode 100644 index 0000000000..99d957594c --- /dev/null +++ b/klibc/klibc/strncat.c @@ -0,0 +1,11 @@ +/* + * strncat.c + */ + +#include <string.h> + +char *strncat(char *dst, const char *src, size_t n) +{ + strncpy(strchr(dst, '\0'), src, n); + return dst; +} diff --git a/klibc/klibc/strncmp.c b/klibc/klibc/strncmp.c new file mode 100644 index 0000000000..98a41c3773 --- /dev/null +++ b/klibc/klibc/strncmp.c @@ -0,0 +1,20 @@ +/* + * strncmp.c + */ + +#include <string.h> + +int strncmp(const char *s1, const char *s2, size_t n) +{ + const unsigned char *c1 = s1, *c2 = s2; + unsigned char ch; + int d = 0; + + while ( n-- ) { + d = (int)*c2++ - (int)(ch = *c1++); + if ( d || !ch ) + break; + } + + return d; +} diff --git a/klibc/klibc/strncpy.c b/klibc/klibc/strncpy.c new file mode 100644 index 0000000000..a8fe45fcbb --- /dev/null +++ b/klibc/klibc/strncpy.c @@ -0,0 +1,22 @@ +/* + * strncpy.c + * + * strncpy() + */ + +#include <string.h> + +char *strncpy(char *dst, const char *src, size_t n) +{ + char *q = dst; + const char *p = src; + char ch; + + while ( n-- ) { + *q++ = ch = *p++; + if ( !ch ) + break; + } + + return dst; +} diff --git a/klibc/klibc/strntoimax.c b/klibc/klibc/strntoimax.c new file mode 100644 index 0000000000..f53a266dba --- /dev/null +++ b/klibc/klibc/strntoimax.c @@ -0,0 +1,13 @@ +/* + * strntoimax.c + * + * strntoimax() + */ + +#include <stddef.h> +#include <inttypes.h> + +intmax_t strntoimax(const char *nptr, char **endptr, int base, size_t n) +{ + return (intmax_t) strntoumax(nptr, endptr, base, n); +} diff --git a/klibc/klibc/strntoumax.c b/klibc/klibc/strntoumax.c new file mode 100644 index 0000000000..4e30637d2c --- /dev/null +++ b/klibc/klibc/strntoumax.c @@ -0,0 +1,75 @@ +/* + * strntoumax.c + * + * The strntoumax() function and associated + */ + +#include <stddef.h> +#include <stdint.h> +#include <ctype.h> + +static inline int digitval(int ch) +{ + if ( ch >= '0' && ch <= '9' ) { + return ch-'0'; + } else if ( ch >= 'A' && ch <= 'Z' ) { + return ch-'A'+10; + } else if ( ch >= 'a' && ch <= 'z' ) { + return ch-'a'+10; + } else { + return -1; + } +} + +uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n) +{ + int minus = 0; + uintmax_t v = 0; + int d; + + while ( n && isspace((unsigned char)*nptr) ) { + nptr++; + n--; + } + + /* Single optional + or - */ + if ( n && *nptr == '-' ) { + minus = 1; + nptr++; + n--; + } else if ( n && *nptr == '+' ) { + nptr++; + } + + if ( base == 0 ) { + if ( n >= 2 && nptr[0] == '0' && + (nptr[1] == 'x' || nptr[1] == 'X') ) { + n -= 2; + nptr += 2; + base = 16; + } else if ( n >= 1 && nptr[0] == '0' ) { + n--; + nptr++; + base = 8; + } else { + base = 10; + } + } else if ( base == 16 ) { + if ( n >= 2 && nptr[0] == '0' && + (nptr[1] == 'x' || nptr[1] == 'X') ) { + n -= 2; + nptr += 2; + } + } + + while ( n && (d = digitval(*nptr)) >= 0 && d < base ) { + v = v*base + d; + n--; + nptr++; + } + + if ( endptr ) + *endptr = (char *)nptr; + + return minus ? -v : v; +} diff --git a/klibc/klibc/strrchr.c b/klibc/klibc/strrchr.c new file mode 100644 index 0000000000..3b42464059 --- /dev/null +++ b/klibc/klibc/strrchr.c @@ -0,0 +1,18 @@ +/* + * strrchr.c + */ + +#include <string.h> + +char *strrchr(const char *s, int c) +{ + const char *found = NULL; + + while ( *s ) { + if ( *s == (char) c ) + found = s; + s++; + } + + return (char *)found; +} diff --git a/klibc/klibc/strsep.c b/klibc/klibc/strsep.c new file mode 100644 index 0000000000..58a7a07773 --- /dev/null +++ b/klibc/klibc/strsep.c @@ -0,0 +1,21 @@ +/* + * strsep.c + */ + +#include <string.h> + +char *strsep(char **stringp, const char *delim) +{ + char *s = *stringp; + char *e; + + if ( !s ) + return NULL; + + e = strpbrk(s, delim); + if (e) + *e++ = '\0'; + + *stringp = e; + return s; +} diff --git a/klibc/klibc/strspn.c b/klibc/klibc/strspn.c new file mode 100644 index 0000000000..856a964197 --- /dev/null +++ b/klibc/klibc/strspn.c @@ -0,0 +1,67 @@ +/* + * strspn, strcspn + */ + +#include <string.h> +#include <stddef.h> +#include <inttypes.h> +#include <limits.h> + +#ifndef LONG_BIT +#define LONG_BIT (CHAR_BIT*sizeof(long)) +#endif + +static inline void +set_bit(unsigned long *bitmap, unsigned int bit) +{ + bitmap[bit/LONG_BIT] |= 1UL << (bit%LONG_BIT); +} + +static inline int +test_bit(unsigned long *bitmap, unsigned int bit) +{ + return (int)(bitmap[bit/LONG_BIT] >> (bit%LONG_BIT)) & 1; +} + +static size_t +strxspn(const char *s, const char *map, int parity) +{ + unsigned long matchmap[((1 << CHAR_BIT)+LONG_BIT-1)/LONG_BIT]; + size_t n = 0; + + /* Create bitmap */ + memset(matchmap, 0, sizeof matchmap); + while ( *map ) + set_bit(matchmap, (unsigned char) *map++); + + /* Make sure the null character never matches */ + if ( parity ) + set_bit(matchmap, 0); + + /* Calculate span length */ + while ( test_bit(matchmap, (unsigned char) *s++)^parity ) + n++; + + return n; +} + +size_t +strspn(const char *s, const char *accept) +{ + return strxspn(s, accept, 0); +} + +size_t +strcspn(const char *s, const char *reject) +{ + return strxspn(s, reject, 1); +} + +char * +strpbrk(const char *s, const char *accept) +{ + const char *ss = s+strxspn(s, accept, 1); + + return *ss ? (char *)ss : NULL; +} + diff --git a/klibc/klibc/strstr.c b/klibc/klibc/strstr.c new file mode 100644 index 0000000000..10222dfd30 --- /dev/null +++ b/klibc/klibc/strstr.c @@ -0,0 +1,10 @@ +/* + * strstr.c + */ + +#include <string.h> + +char *strstr(const char *haystack, const char *needle) +{ + return (char *)memmem(haystack, strlen(haystack), needle, strlen(needle)); +} diff --git a/klibc/klibc/strtoimax.c b/klibc/klibc/strtoimax.c new file mode 100644 index 0000000000..0cdd088e51 --- /dev/null +++ b/klibc/klibc/strtoimax.c @@ -0,0 +1,3 @@ +#define TYPE intmax_t +#define NAME strtoimax +#include "strtox.c" diff --git a/klibc/klibc/strtok.c b/klibc/klibc/strtok.c new file mode 100644 index 0000000000..6e84f1dff3 --- /dev/null +++ b/klibc/klibc/strtok.c @@ -0,0 +1,16 @@ +/* + * strtok.c + */ + +#include <string.h> + +char *strtok(char *s, const char *delim) +{ + static char *holder; + + if ( s ) + holder = s; + + return strsep(&holder, delim); +} + diff --git a/klibc/klibc/strtol.c b/klibc/klibc/strtol.c new file mode 100644 index 0000000000..9efc8b9e4a --- /dev/null +++ b/klibc/klibc/strtol.c @@ -0,0 +1,3 @@ +#define TYPE signed long +#define NAME strtol +#include "strtox.c" diff --git a/klibc/klibc/strtoll.c b/klibc/klibc/strtoll.c new file mode 100644 index 0000000000..a9428c7f14 --- /dev/null +++ b/klibc/klibc/strtoll.c @@ -0,0 +1,3 @@ +#define TYPE signed long long +#define NAME strtoll +#include "strtox.c" diff --git a/klibc/klibc/strtoul.c b/klibc/klibc/strtoul.c new file mode 100644 index 0000000000..3189aaa7ce --- /dev/null +++ b/klibc/klibc/strtoul.c @@ -0,0 +1,3 @@ +#define TYPE unsigned long +#define NAME strtoul +#include "strtox.c" diff --git a/klibc/klibc/strtoull.c b/klibc/klibc/strtoull.c new file mode 100644 index 0000000000..83c14e9128 --- /dev/null +++ b/klibc/klibc/strtoull.c @@ -0,0 +1,3 @@ +#define TYPE unsigned long long +#define NAME strtoull +#include "strtox.c" diff --git a/klibc/klibc/strtoumax.c b/klibc/klibc/strtoumax.c new file mode 100644 index 0000000000..a3797105e8 --- /dev/null +++ b/klibc/klibc/strtoumax.c @@ -0,0 +1,3 @@ +#define TYPE uintmax_t +#define NAME strtoumax +#include "strtox.c" diff --git a/klibc/klibc/strtox.c b/klibc/klibc/strtox.c new file mode 100644 index 0000000000..7c228b6fa4 --- /dev/null +++ b/klibc/klibc/strtox.c @@ -0,0 +1,13 @@ +/* + * strtox.c + * + * strto...() functions, by macro definition + */ + +#include <stddef.h> +#include <inttypes.h> + +TYPE NAME (const char *nptr, char **endptr, int base) +{ + return (TYPE) strntoumax(nptr, endptr, base, ~(size_t)0); +} diff --git a/klibc/klibc/syscalls.pl b/klibc/klibc/syscalls.pl new file mode 100644 index 0000000000..b530a9b8c7 --- /dev/null +++ b/klibc/klibc/syscalls.pl @@ -0,0 +1,81 @@ +#!/usr/bin/perl +($arch, $file) = @ARGV; + +if (!open(FILE, "< $file")) { + print STDERR "$file: $!\n"; + exit(1); +} + +while ( defined($line = <FILE>) ) { + chomp $line; + $line =~ s/\s*\#.*$//; # Strip comments and trailing blanks + next unless $line; + + if ( $line =~ /^\s*(\<[^\>]+\>\s+|)([^\(\<\>]+[^\@\:A-Za-z0-9_])([A-Za-z0-9_]+)(|\@[A-Za-z0-9_]+)(|\:\:[A-Za-z0-9_]+)\s*\(([^\:\)]*)\)\s*$/ ) { + $archs = $1; + $type = $2; + $sname = $3; + $stype = $4; + $fname = $5; + $argv = $6; + + $doit = 1; + if ( $archs ne '' ) { + die "$0: Internal error" + unless ( $archs =~ /^\<(|\!)([^\>\!]+)\>/ ); + $not = $1; + $list = $2; + + $doit = ($not eq '') ? 0 : 1; + + @list = split(/,/, $list); + foreach $a ( @list ) { + if ( $a eq $arch ) { + $doit = ($not eq '') ? 1 : 0; + last; + } + } + } + next if ( ! $doit ); + + $type =~ s/\s*$//; + + $stype =~ s/^\@/_/; + + if ( $fname eq '' ) { + $fname = $sname; + } else { + $fname =~ s/^\:\://; + } + + @args = split(/\s*\,\s*/, $argv); + + open(OUT, "> syscalls/${fname}.c") + or die "$0: Cannot open syscalls/${fname}.c\n"; + + if ( $fname eq "rt_sigaction") { + print OUT "#ifdef __x86_64__\n\n"; + print OUT "struct sigaction;\n\n"; + print OUT "#endif\n\n" + } + + print OUT "#include \"syscommon.h\"\n\n"; + + if ( $fname ne $sname ) { + print OUT "#undef __NR_${fname}\n"; + print OUT "#define __NR_${fname} __NR_${sname}\n\n"; + } + + print OUT "_syscall", scalar(@args), $stype, "(", $type, ',', $fname; + + $i = 0; + foreach $arg ( @args ) { + print OUT ",", $arg, ",a",$i++; + } + print OUT ");\n"; + close(OUT); + } else { + print STDERR "$file:$.: Could not parse input\n"; + exit(1); + } +} diff --git a/klibc/klibc/syscommon.h b/klibc/klibc/syscommon.h new file mode 100644 index 0000000000..224e240e38 --- /dev/null +++ b/klibc/klibc/syscommon.h @@ -0,0 +1,29 @@ +/* + * syscommon.h + * + * Common header file for system call stubs + */ + +#define __IN_SYS_COMMON +#include <errno.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/syscall.h> + +#include <poll.h> +#include <sched.h> +#include <sys/dirent.h> +#include <sys/klog.h> +#include <sys/mman.h> +#include <sys/module.h> +#include <sys/resource.h> +#include <sys/select.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/times.h> +#include <sys/uio.h> +#include <sys/utime.h> +#include <sys/utsname.h> +#include <sys/vfs.h> +#include <sys/wait.h> +#include <unistd.h> diff --git a/klibc/klibc/syslog.c b/klibc/klibc/syslog.c new file mode 100644 index 0000000000..b031d4f0e7 --- /dev/null +++ b/klibc/klibc/syslog.c @@ -0,0 +1,74 @@ +/* + * syslog.c + * + * Issue syslog messages via the kernel printk queue. + */ + +#include <stdio.h> +#include <string.h> +#include <stdarg.h> +#include <syslog.h> +#include <unistd.h> +#include <fcntl.h> + +/* Maximum size for a kernel message */ +#define BUFLEN 1024 + +/* Logging node */ +#define LOGDEV "/dev/kmsg" + +/* Max length of ID string */ +#define MAXID 31 + +int __syslog_fd = -1; +static char id[MAXID+1]; + +void openlog(const char *ident, int option, int facility) +{ + int fd; + + (void)option; (void)facility; /* Unused */ + + if ( __syslog_fd == -1 ) { + __syslog_fd = fd = open(LOGDEV, O_WRONLY); + if ( fd == -1 ) + return; + fcntl(fd, F_SETFD, (long)FD_CLOEXEC); + } + + strncpy(id, ident?ident:"", MAXID); + id[MAXID] = '\0'; /* Make sure it's null-terminated */ +} + +void syslog(int prio, const char *format, ...) +{ + va_list ap; + char buf[BUFLEN]; + int rv, len; + int fd; + + if ( __syslog_fd == -1 ) + openlog(NULL, 0, 0); + + fd = __syslog_fd; + if ( fd == -1 ) + fd = 2; /* Failed to open log, write to stderr */ + + buf[0] = '<'; + buf[1] = LOG_PRI(prio)+'0'; + buf[2] = '>'; + len = 3; + + if ( *id ) + len += sprintf(buf+3, "%s: ", id); + + va_start(ap, format); + rv = vsnprintf(buf+len, BUFLEN-len, format, ap); + va_end(ap); + + len += rv; + if ( len > BUFLEN-1 ) len = BUFLEN-1; + buf[len] = '\n'; + + write(fd, buf, len+1); +} diff --git a/klibc/klibc/system.c b/klibc/klibc/system.c new file mode 100644 index 0000000000..643bf5e1cc --- /dev/null +++ b/klibc/klibc/system.c @@ -0,0 +1,61 @@ +/* + * system.c + * + * The system() function. If this turns out to actually be *used*, + * we may want to try to detect the very simple cases (no shell magic) + * and handle them internally, instead of requiring that /bin/sh be + * present. + */ + +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> +#include <signal.h> +#include <sys/wait.h> + +int system(const char *string) +{ + pid_t pid; + struct sigaction ignore, old_int, old_quit; + sigset_t masked, oldmask; + static const char *argv[] = { "/bin/sh", "-c", NULL, NULL }; + int status; + + /* Block SIGCHLD and ignore SIGINT and SIGQUIT */ + /* Do this before the fork() to avoid races */ + + ignore.sa_handler = SIG_IGN; + sigemptyset(&ignore.sa_mask); + ignore.sa_flags = 0; + sigaction(SIGINT, &ignore, &old_int); + sigaction(SIGQUIT, &ignore, &old_quit); + + sigemptyset(&masked); + sigaddset(&masked, SIGCHLD); + sigprocmask(SIG_BLOCK, &masked, &oldmask); + + pid = fork(); + + if ( pid < 0 ) + return -1; + else if ( pid == 0 ) { + sigaction(SIGINT, &old_int, NULL); + sigaction(SIGQUIT, &old_quit, NULL); + sigprocmask(SIG_SETMASK, &oldmask, NULL); + + argv[2] = string; + + execve(argv[0], (char * const *)argv, (char * const *)environ); + _exit(127); + } + + /* else... */ + + waitpid(pid, &status, 0); + + sigaction(SIGINT, &old_int, NULL); + sigaction(SIGQUIT, &old_quit, NULL); + sigprocmask(SIG_SETMASK, &oldmask, NULL); + + return status; +} diff --git a/klibc/klibc/tests/getenvtest.c b/klibc/klibc/tests/getenvtest.c new file mode 100644 index 0000000000..07cac0cef7 --- /dev/null +++ b/klibc/klibc/tests/getenvtest.c @@ -0,0 +1,26 @@ +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> + +int main(int argc, char *argv[], char *envp[]) +{ + int i; + + /* Verify envp == environ */ + printf("Verifying envp == environ... %s\n", + (envp == environ) ? "ok" : "ERROR"); + + /* Test argc/argv */ + printf("argc = %d, argv = %p\n", argc, argv); + for ( i = 0 ; i < argc ; i++ ) { + printf("argv[%2d] = %s\n", i, argv[i]); + } + + /* Test environ */ + printf("PATH = %s\n", getenv("PATH")); + printf("HOME = %s\n", getenv("HOME")); + printf("TERM = %s\n", getenv("TERM")); + printf("USER = %s\n", getenv("USER")); + + return 0; +} diff --git a/klibc/klibc/tests/getopttest.c b/klibc/klibc/tests/getopttest.c new file mode 100644 index 0000000000..90ceaa2c58 --- /dev/null +++ b/klibc/klibc/tests/getopttest.c @@ -0,0 +1,31 @@ +/* + * getopttest.c + * + * Simple test for getopt, set the environment variable GETOPTTEST + * to give the argument string to getopt() + */ + +#include <stdlib.h> +#include <unistd.h> +#include <stdio.h> + +int main(int argc, char * const *argv) +{ + const char *parser; + char showchar[] = "\'?\'"; + int c; + + parser = getenv("GETOPTTEST"); + if ( !parser ) parser = "abzf:o:"; + + do { + c = getopt(argc, argv, parser); + showchar[1] = c; + printf("c = %s, optind = %d (%s), optarg = \"%s\", optopt = \'%c\'\n", + (c == EOF) ? "EOF" : showchar, + optind, argv[optind], optarg, optopt); + } while ( c != -1 ); + + return 0; +} + diff --git a/klibc/klibc/tests/hello.c b/klibc/klibc/tests/hello.c new file mode 100644 index 0000000000..20457af153 --- /dev/null +++ b/klibc/klibc/tests/hello.c @@ -0,0 +1,7 @@ +#include <stdio.h> + +int main(void) +{ + printf("Hello, World!\n"); + return 0; +} diff --git a/klibc/klibc/tests/idtest.c b/klibc/klibc/tests/idtest.c new file mode 100644 index 0000000000..c3c44479c5 --- /dev/null +++ b/klibc/klibc/tests/idtest.c @@ -0,0 +1,14 @@ +#include <stdio.h> +#include <unistd.h> + +int main(void) +{ + printf("pid = %u\n", getpid()); + printf("ppid = %u\n", getppid()); + printf("uid = %u\n", getuid()); + printf("euid = %u\n", geteuid()); + printf("gid = %u\n", getgid()); + printf("egid = %u\n", getegid()); + sleep(10); + return 0; +} diff --git a/klibc/klibc/tests/malloctest.c b/klibc/klibc/tests/malloctest.c new file mode 100644 index 0000000000..64e8e79851 --- /dev/null +++ b/klibc/klibc/tests/malloctest.c @@ -0,0 +1,4145 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#define NCYCLES 4096 + +int sizes[NCYCLES] = { + 11986, + 277806, + 2659, + 46, + 0, + 775553, + 1991, + 21, + 7638, + 250197, + 155828, + 5777, + 9, + 315006, + 900788, + 0, + 24893, + 119996, + 72299, + 171266, + 357, + 560, + 368, + 22952, + 54058, + 12638, + 39155, + 2738, + 217563, + 26853, + 47, + 75, + 1167, + 16917, + 1899, + 2905, + 9337, + 62243, + 14214, + 270523, + 4024, + 21, + 32, + 14892, + 625144, + 13, + 21700, + 8804, + 254147, + 0, + 6, + 836004, + 1718, + 2289, + 15554, + 412857, + 185097, + 806709, + 64, + 18602, + 17064, + 1779, + 78153, + 170600, + 199100, + 546528, + 0, + 21, + 20609, + 16514, + 548196, + 311446, + 53484, + 0, + 551, + 22225, + 24, + 153989, + 457309, + 526833, + 227979, + 757167, + 429560, + 0, + 835, + 1702, + 475275, + 798416, + 753, + 0, + 11126, + 145779, + 2006, + 0, + 8182, + 0, + 569432, + 9671, + 36, + 5523, + 407325, + 0, + 65, + 9293, + 0, + 6793, + 468701, + 73, + 0, + 186236, + 0, + 328405, + 125616, + 508013, + 380519, + 599518, + 83, + 151973, + 466906, + 9029, + 159725, + 1316, + 1, + 911532, + 1508, + 19050, + 972850, + 126, + 439377, + 29, + 37928, + 149628, + 54, + 130248, + 2, + 143, + 0, + 716873, + 3327, + 5, + 116131, + 5124, + 559621, + 2886, + 534, + 186432, + 441, + 7348, + 10331, + 1, + 260935, + 7, + 4370, + 405415, + 2, + 84518, + 1970, + 1, + 281910, + 46, + 274, + 2273, + 370565, + 4190, + 820641, + 577970, + 32809, + 974893, + 398067, + 380698, + 4, + 25978, + 153, + 882668, + 312365, + 9523, + 156421, + 0, + 268143, + 6, + 2, + 42987, + 212, + 12303, + 6723, + 1179, + 0, + 120924, + 3877, + 330421, + 310445, + 39264, + 8, + 85380, + 464716, + 0, + 33657, + 6285, + 0, + 4491, + 229, + 50, + 373197, + 6029, + 19, + 86884, + 243745, + 335656, + 90945, + 38973, + 572950, + 164129, + 0, + 3, + 17, + 13579, + 4448, + 47, + 3, + 132966, + 726249, + 498503, + 256, + 0, + 25841, + 0, + 7, + 945380, + 11872, + 69, + 3799, + 77223, + 1914, + 73, + 810968, + 10223, + 257918, + 184252, + 350, + 8101, + 725, + 9, + 2, + 2089, + 175, + 247, + 185964, + 36517, + 3723, + 313465, + 209, + 1300, + 128071, + 7425, + 2436, + 62, + 13753, + 9514, + 41, + 409141, + 46643, + 20866, + 15664, + 388548, + 84692, + 9549, + 610, + 7213, + 14, + 14930, + 244719, + 4748, + 41682, + 401098, + 102506, + 176535, + 0, + 5133, + 548, + 5234, + 56, + 11101, + 87638, + 336579, + 291705, + 640250, + 768165, + 370, + 2809, + 3, + 0, + 445122, + 47190, + 24885, + 143556, + 84, + 504726, + 610020, + 40355, + 902230, + 4360, + 1747, + 3496, + 489501, + 19, + 801601, + 62189, + 48, + 2645, + 320601, + 27304, + 17740, + 344, + 10, + 991, + 925503, + 0, + 315, + 251, + 3611, + 1756, + 683, + 165, + 380132, + 181101, + 453041, + 892056, + 67191, + 252592, + 32407, + 56242, + 8, + 297173, + 542903, + 830334, + 585236, + 422555, + 44769, + 0, + 68, + 4143, + 38754, + 73539, + 44579, + 94001, + 428537, + 38554, + 106612, + 0, + 182987, + 831731, + 3605, + 752851, + 52, + 72, + 120872, + 963754, + 31, + 764, + 240592, + 99101, + 328538, + 440325, + 12211, + 151282, + 353436, + 2991, + 40710, + 5212, + 5106, + 139122, + 148915, + 498505, + 1366, + 516, + 29190, + 17, + 224208, + 40, + 89, + 19190, + 8, + 25377, + 10029, + 720, + 97963, + 0, + 614, + 244567, + 2113, + 903675, + 8388, + 6, + 390705, + 325006, + 284272, + 108086, + 17, + 2628, + 952530, + 20474, + 898276, + 138661, + 3883, + 903, + 569993, + 376918, + 5849, + 103404, + 794499, + 35388, + 5, + 0, + 961626, + 27415, + 1927, + 92036, + 46241, + 35978, + 7426, + 399884, + 29490, + 252655, + 675971, + 3509, + 54170, + 170790, + 831341, + 134579, + 0, + 790422, + 35, + 930830, + 97394, + 20265, + 670, + 38497, + 1759, + 71209, + 93, + 736, + 11, + 886, + 1961, + 7, + 210607, + 62226, + 186736, + 1518, + 5, + 5, + 13, + 66989, + 442321, + 0, + 607939, + 11253, + 210875, + 495530, + 2, + 221136, + 377663, + 372, + 200658, + 18591, + 129783, + 803411, + 867506, + 757446, + 48836, + 34, + 200, + 114983, + 7287, + 22849, + 226669, + 13, + 0, + 20164, + 7828, + 39, + 49448, + 26740, + 185566, + 9927, + 36192, + 91068, + 338368, + 926, + 27746, + 534794, + 936132, + 2922, + 5, + 183162, + 256846, + 242551, + 134318, + 212959, + 167162, + 470, + 477045, + 532116, + 483794, + 733, + 5335, + 83074, + 4686, + 9567, + 1, + 195100, + 40354, + 87338, + 369, + 800, + 0, + 194504, + 469051, + 363532, + 850574, + 5085, + 167027, + 794511, + 124320, + 303231, + 132195, + 13225, + 46333, + 4313, + 89, + 799, + 51482, + 0, + 26, + 12659, + 1045, + 23621, + 0, + 74926, + 490979, + 6, + 3188, + 9448, + 174730, + 38982, + 102317, + 189621, + 853, + 29227, + 43374, + 423, + 420951, + 686, + 128, + 31291, + 0, + 402819, + 663143, + 55903, + 142, + 2, + 331584, + 197164, + 7, + 671983, + 53, + 5020, + 9782, + 123, + 743407, + 1276, + 1115, + 1169, + 122752, + 824690, + 292030, + 2094, + 144626, + 0, + 297278, + 440, + 742, + 95879, + 17682, + 10654, + 31, + 22183, + 746, + 0, + 0, + 11185, + 28, + 394987, + 36, + 474, + 243749, + 1431, + 56702, + 76, + 15619, + 33071, + 12181, + 158647, + 261786, + 1, + 119783, + 48816, + 6278, + 4121, + 61122, + 69, + 48790, + 345335, + 275917, + 964393, + 424, + 586433, + 20519, + 18156, + 756400, + 27736, + 458706, + 1, + 3286, + 929624, + 1883, + 2, + 1086, + 439501, + 552, + 157132, + 5565, + 105061, + 8199, + 23, + 178797, + 0, + 130644, + 1, + 6952, + 754, + 500, + 647683, + 0, + 959079, + 622561, + 1131, + 559783, + 6862, + 175420, + 408671, + 463461, + 55908, + 606496, + 169, + 49060, + 247, + 953, + 333030, + 0, + 23399, + 29193, + 9303, + 15, + 515402, + 34961, + 365856, + 633043, + 173, + 556089, + 1809, + 12215, + 14, + 316, + 20642, + 9, + 15, + 190391, + 951463, + 25059, + 13654, + 385040, + 4272, + 929033, + 208813, + 35166, + 42849, + 662648, + 254811, + 4230, + 812459, + 681, + 390168, + 5381, + 4662, + 173257, + 478863, + 103, + 89332, + 0, + 0, + 589484, + 19369, + 94, + 9, + 639917, + 1110, + 393, + 101040, + 911, + 152899, + 0, + 2, + 0, + 0, + 335691, + 43694, + 62273, + 200121, + 2250, + 621004, + 149918, + 41063, + 218229, + 0, + 497924, + 16832, + 587071, + 0, + 0, + 729918, + 2, + 808513, + 9417, + 718, + 0, + 2769, + 28704, + 1335, + 734726, + 219157, + 786230, + 981004, + 350788, + 884529, + 0, + 87872, + 34647, + 85469, + 4524, + 339838, + 38228, + 0, + 4151, + 1145, + 0, + 351, + 167956, + 810075, + 689, + 251212, + 583068, + 2929, + 189456, + 2089, + 48749, + 278952, + 77134, + 0, + 0, + 45595, + 281829, + 969602, + 43999, + 69824, + 856982, + 61732, + 336, + 25488, + 213, + 46683, + 1909, + 174097, + 57930, + 91466, + 828418, + 95740, + 378828, + 128065, + 68068, + 0, + 13312, + 26006, + 6760, + 51, + 276081, + 640068, + 634985, + 7131, + 784882, + 790126, + 628585, + 205824, + 764965, + 17793, + 3159, + 649924, + 0, + 37383, + 9919, + 353, + 0, + 149003, + 620629, + 95928, + 2560, + 504343, + 1000, + 32, + 43836, + 407031, + 207, + 800894, + 3222, + 51028, + 7, + 6, + 22010, + 0, + 21174, + 12893, + 824932, + 7305, + 70, + 624258, + 372139, + 21504, + 387996, + 418931, + 914268, + 576, + 0, + 0, + 618224, + 787516, + 133014, + 422, + 383124, + 656318, + 4420, + 6082, + 244813, + 38585, + 3200, + 1, + 2, + 11882, + 113, + 45581, + 13121, + 95475, + 807219, + 8195, + 995116, + 13, + 2146, + 369925, + 60103, + 25, + 125165, + 51300, + 4894, + 173261, + 74186, + 1044, + 122992, + 1243, + 21703, + 26294, + 197, + 333825, + 426872, + 719580, + 3598, + 106, + 0, + 9932, + 61509, + 146, + 721428, + 964781, + 319850, + 573802, + 7458, + 317889, + 0, + 133086, + 87836, + 60496, + 304249, + 1565, + 27, + 42, + 899324, + 189637, + 8648, + 104570, + 901598, + 447765, + 24, + 108, + 120127, + 828626, + 8, + 899514, + 28, + 13, + 7576, + 163390, + 1625, + 3023, + 155175, + 2, + 391, + 1, + 493073, + 398, + 210771, + 26266, + 287999, + 38255, + 249666, + 598202, + 119601, + 216933, + 91205, + 0, + 7247, + 77077, + 565383, + 29102, + 253641, + 48855, + 19722, + 463536, + 40182, + 65393, + 829444, + 598402, + 1590, + 798, + 467, + 834847, + 3007, + 13711, + 0, + 195, + 101662, + 255749, + 129201, + 11965, + 1781, + 13349, + 3100, + 718066, + 99, + 712450, + 888215, + 42503, + 43171, + 494946, + 0, + 2175, + 12387, + 25662, + 78, + 739030, + 0, + 19, + 427526, + 4275, + 5583, + 0, + 2447, + 132398, + 26437, + 3873, + 440035, + 21, + 6, + 35432, + 41523, + 7179, + 712703, + 428868, + 2793, + 6, + 286277, + 1882, + 95116, + 2959, + 86, + 115425, + 81386, + 59836, + 37, + 247598, + 34732, + 249, + 500110, + 5589, + 40319, + 575, + 12145, + 385829, + 565600, + 582150, + 92, + 223209, + 0, + 910, + 1048, + 47329, + 90944, + 235, + 8739, + 686685, + 1753, + 126, + 434, + 609477, + 25021, + 6610, + 52675, + 4, + 717846, + 150864, + 418583, + 17751, + 513794, + 181362, + 329556, + 10426, + 717019, + 457, + 616, + 388984, + 17, + 8338, + 59531, + 32, + 99565, + 376146, + 134578, + 966, + 0, + 0, + 174, + 2105, + 555, + 8990, + 298, + 169932, + 247281, + 240918, + 298655, + 158743, + 15994, + 95708, + 51, + 2985, + 4294, + 731934, + 185640, + 1483, + 87, + 742033, + 9, + 1345, + 3680, + 133530, + 9355, + 800111, + 28508, + 0, + 369, + 31681, + 24, + 8237, + 313380, + 4732, + 275423, + 951592, + 0, + 41381, + 225515, + 393004, + 526, + 187, + 19515, + 6006, + 28923, + 310151, + 2390, + 374, + 0, + 19142, + 72, + 114, + 193305, + 24035, + 397067, + 18, + 14839, + 3473, + 164, + 104622, + 378958, + 2218, + 0, + 89053, + 105183, + 312265, + 82146, + 147210, + 3419, + 5178, + 34948, + 46836, + 41319, + 842825, + 595972, + 0, + 249625, + 325, + 608, + 372328, + 119634, + 7504, + 920214, + 7302, + 444532, + 359213, + 27265, + 1755, + 48, + 126799, + 651270, + 818220, + 799493, + 724024, + 64047, + 73699, + 206999, + 209, + 1581, + 0, + 42937, + 301144, + 73416, + 0, + 242058, + 29660, + 3, + 34709, + 162719, + 2863, + 3992, + 5212, + 151814, + 3092, + 198001, + 44331, + 36, + 407, + 364771, + 1349, + 502772, + 214726, + 607, + 388583, + 137660, + 337124, + 13279, + 10549, + 943075, + 164068, + 19157, + 38443, + 26351, + 0, + 67167, + 735, + 46486, + 130305, + 232330, + 744, + 882337, + 2, + 69275, + 126354, + 9370, + 2845, + 299, + 38988, + 37834, + 0, + 306433, + 9139, + 237132, + 0, + 500, + 13462, + 373684, + 107453, + 381924, + 347915, + 4329, + 1668, + 3960, + 370661, + 3614, + 636048, + 0, + 487449, + 64925, + 333894, + 11, + 52192, + 531200, + 155554, + 461, + 1547, + 994361, + 11955, + 321056, + 37425, + 14249, + 69151, + 621862, + 174, + 79607, + 34, + 77577, + 13723, + 267550, + 13801, + 698, + 12, + 171556, + 57354, + 676845, + 0, + 24965, + 908955, + 570483, + 0, + 296387, + 983966, + 85012, + 130298, + 151946, + 384474, + 731455, + 150699, + 772, + 216131, + 346, + 130935, + 3472, + 18, + 426045, + 677262, + 808, + 17030, + 5188, + 0, + 491153, + 67299, + 19, + 60342, + 69, + 0, + 76478, + 95763, + 0, + 28778, + 147869, + 335927, + 27846, + 2163, + 22750, + 162, + 23, + 11391, + 469099, + 5852, + 63, + 0, + 0, + 22193, + 165, + 489007, + 9249, + 12477, + 2841, + 223532, + 13877, + 173, + 3570, + 45477, + 233073, + 23296, + 64377, + 4910, + 8, + 76246, + 411147, + 287411, + 10450, + 3667, + 1, + 500933, + 31363, + 257, + 1705, + 6036, + 49934, + 13738, + 13485, + 61608, + 561978, + 76493, + 16377, + 1817, + 0, + 235600, + 0, + 16347, + 680478, + 5115, + 895607, + 138270, + 369912, + 53110, + 0, + 647083, + 85, + 458681, + 163227, + 52767, + 196, + 267719, + 14047, + 147293, + 814457, + 174896, + 0, + 34138, + 36, + 21575, + 3, + 0, + 0, + 38391, + 2597, + 2, + 1433, + 3807, + 36476, + 287, + 141530, + 29389, + 495655, + 30014, + 0, + 550766, + 11958, + 348, + 226760, + 15, + 251353, + 675788, + 518308, + 215, + 81987, + 409862, + 559596, + 114283, + 4925, + 0, + 17, + 14221, + 0, + 162, + 766370, + 4898, + 998, + 493, + 138418, + 265159, + 12152, + 5229, + 1204, + 1814, + 432530, + 2889, + 144, + 1149, + 35886, + 636931, + 6640, + 1508, + 414118, + 858, + 20039, + 17398, + 3, + 5094, + 6, + 13996, + 6754, + 362, + 451487, + 11471, + 7896, + 330009, + 244269, + 99928, + 0, + 14311, + 9949, + 15251, + 283923, + 123754, + 188360, + 93902, + 854384, + 548001, + 531788, + 26298, + 328479, + 941, + 246535, + 106320, + 28769, + 440, + 4, + 61262, + 55615, + 170, + 989327, + 692534, + 8063, + 445842, + 4434, + 255349, + 117781, + 6, + 9249, + 136216, + 38165, + 307012, + 12, + 2341, + 18062, + 371882, + 662154, + 12623, + 176847, + 332220, + 590935, + 33682, + 0, + 121374, + 67, + 46841, + 495890, + 640, + 19, + 14737, + 11032, + 17, + 5993, + 302562, + 827710, + 165346, + 49607, + 87863, + 308513, + 735300, + 1914, + 2900, + 207308, + 9068, + 83494, + 179, + 417, + 41605, + 74681, + 652171, + 4013, + 29811, + 13966, + 8136, + 78, + 61182, + 674187, + 0, + 331121, + 0, + 18559, + 386, + 77, + 348439, + 975358, + 18, + 33700, + 47396, + 204751, + 2350, + 26503, + 0, + 83653, + 446, + 10844, + 485, + 9241, + 88347, + 232419, + 936900, + 43250, + 2, + 26112, + 811955, + 20723, + 102069, + 42255, + 8431, + 119508, + 4080, + 13565, + 12, + 46110, + 62096, + 638777, + 44025, + 152985, + 13362, + 3, + 12331, + 193337, + 56419, + 14593, + 3837, + 282314, + 403454, + 48589, + 135, + 18350, + 2160, + 90, + 918216, + 7083, + 105534, + 742826, + 399028, + 1470, + 23770, + 480, + 677884, + 340472, + 107406, + 0, + 5002, + 445, + 748948, + 534012, + 592464, + 6539, + 819632, + 3138, + 4, + 39397, + 229683, + 12204, + 2439, + 65131, + 817226, + 22596, + 0, + 1046, + 94638, + 0, + 95403, + 1230, + 790056, + 19976, + 43085, + 14251, + 139187, + 20232, + 693, + 3058, + 27654, + 65690, + 40948, + 15001, + 21089, + 14425, + 322459, + 13571, + 228154, + 536814, + 761221, + 28030, + 2322, + 921, + 1, + 1137, + 187815, + 8, + 34911, + 4527, + 15, + 46, + 78801, + 0, + 73605, + 44, + 28233, + 1370, + 73409, + 198159, + 66586, + 3, + 2576, + 15, + 35460, + 263237, + 44997, + 2873, + 240, + 1781, + 269, + 46, + 272778, + 28404, + 8232, + 417073, + 234591, + 9, + 720349, + 1176, + 16195, + 0, + 9705, + 0, + 14, + 947048, + 163, + 76288, + 1115, + 267020, + 3416, + 414217, + 441004, + 95131, + 765002, + 6196, + 9069, + 27017, + 137039, + 65247, + 266489, + 484945, + 187008, + 45405, + 5700, + 9, + 7751, + 12, + 294, + 3093, + 6350, + 103303, + 6045, + 252345, + 140207, + 22390, + 234867, + 443326, + 1, + 0, + 89972, + 8637, + 427150, + 22146, + 0, + 310432, + 390333, + 10461, + 1632, + 31403, + 908653, + 0, + 6543, + 163479, + 67608, + 195543, + 315889, + 822964, + 383536, + 954954, + 1619, + 241, + 96053, + 104556, + 767302, + 2469, + 12, + 164330, + 78, + 141, + 170519, + 268214, + 53338, + 48342, + 721, + 58980, + 4345, + 1, + 856265, + 87289, + 57219, + 775679, + 123992, + 695804, + 113025, + 832, + 117420, + 16634, + 352, + 24729, + 14973, + 25622, + 131290, + 0, + 22, + 87740, + 5917, + 533, + 2934, + 34261, + 9174, + 0, + 1656, + 764587, + 54652, + 35597, + 36389, + 577889, + 63957, + 26808, + 34556, + 56, + 15641, + 137, + 1, + 3, + 11724, + 197397, + 39027, + 87902, + 320, + 791479, + 7, + 487864, + 0, + 433, + 25733, + 6956, + 15407, + 312557, + 526302, + 383019, + 340215, + 96, + 276158, + 6493, + 135613, + 2000, + 1218, + 930, + 276808, + 273249, + 8896, + 397, + 735095, + 20648, + 2079, + 5349, + 205, + 356313, + 841954, + 8255, + 266874, + 0, + 965, + 287993, + 1549, + 207833, + 75, + 178180, + 39072, + 0, + 43254, + 3847, + 227, + 2712, + 161043, + 463264, + 74720, + 795789, + 12, + 6812, + 202804, + 29379, + 64241, + 132121, + 790622, + 493588, + 0, + 48, + 147352, + 925197, + 38149, + 18380, + 0, + 270280, + 633, + 3373, + 31294, + 7830, + 0, + 0, + 11371, + 56143, + 5393, + 74724, + 495109, + 0, + 18993, + 21524, + 0, + 53889, + 400509, + 204563, + 0, + 11625, + 9635, + 0, + 1678, + 12096, + 59, + 817112, + 10002, + 128209, + 11593, + 17313, + 15200, + 106796, + 261401, + 707077, + 0, + 314030, + 798591, + 14175, + 5668, + 2766, + 0, + 566, + 5543, + 24112, + 154482, + 5642, + 0, + 38410, + 3, + 4, + 700724, + 25024, + 5, + 407, + 564150, + 672, + 143, + 2049, + 574708, + 65858, + 213412, + 3797, + 511, + 30907, + 1212, + 765, + 2127, + 481, + 130048, + 113816, + 39861, + 153169, + 503378, + 523944, + 111, + 55083, + 698, + 275, + 3, + 3195, + 1657, + 0, + 317881, + 6672, + 543, + 153011, + 77240, + 9338, + 889850, + 29518, + 872485, + 181927, + 376086, + 266, + 409, + 4, + 14856, + 31943, + 2448, + 8, + 75, + 383097, + 294366, + 0, + 173084, + 753160, + 66457, + 725783, + 51, + 127651, + 1073, + 12598, + 140080, + 0, + 296375, + 581720, + 217346, + 8272, + 2051, + 185390, + 520645, + 1260, + 13873, + 168040, + 19690, + 103347, + 295011, + 548404, + 48, + 4, + 916417, + 1948, + 621365, + 263245, + 2792, + 86803, + 181193, + 558081, + 50907, + 442770, + 51448, + 340276, + 1346, + 607, + 459627, + 0, + 30, + 73298, + 15389, + 12264, + 2719, + 2936, + 143043, + 209970, + 0, + 42, + 6657, + 317419, + 0, + 32622, + 524000, + 0, + 310331, + 303778, + 268710, + 9, + 10410, + 25343, + 949506, + 784353, + 3861, + 46823, + 251292, + 75008, + 269798, + 87731, + 112813, + 571679, + 385, + 3, + 2811, + 36025, + 9243, + 935128, + 906, + 10688, + 25, + 86757, + 307, + 55, + 22, + 2, + 61, + 620426, + 484530, + 633806, + 0, + 1342, + 9293, + 992181, + 503, + 195433, + 46150, + 893091, + 3207, + 2865, + 72894, + 830299, + 355, + 327479, + 0, + 35573, + 3068, + 15699, + 31187, + 55378, + 416067, + 91721, + 159, + 0, + 255139, + 2104, + 19, + 606757, + 323, + 902659, + 365655, + 400, + 903, + 408, + 385, + 21774, + 701290, + 234426, + 17020, + 950, + 0, + 0, + 429, + 1245, + 405871, + 1097, + 280634, + 74, + 158233, + 1583, + 180333, + 42114, + 575973, + 539327, + 59252, + 121928, + 165, + 148501, + 55757, + 7494, + 127728, + 7832, + 68504, + 619770, + 70995, + 312816, + 7307, + 38265, + 46248, + 363304, + 269442, + 77112, + 448331, + 910442, + 474418, + 152752, + 752, + 104912, + 408492, + 691709, + 632381, + 48519, + 20524, + 344294, + 14670, + 0, + 21607, + 81162, + 181458, + 0, + 908322, + 7261, + 10888, + 58054, + 1788, + 970933, + 5925, + 121553, + 36152, + 588267, + 23615, + 1850, + 30728, + 3599, + 1319, + 6027, + 0, + 32141, + 984156, + 436781, + 15003, + 621407, + 9412, + 562911, + 189740, + 377895, + 656800, + 197, + 14413, + 99382, + 384, + 11480, + 0, + 86118, + 881961, + 1905, + 82061, + 4140, + 741153, + 26, + 687, + 12251, + 10945, + 209267, + 220602, + 135881, + 6, + 237945, + 158, + 5, + 76303, + 81344, + 986042, + 956063, + 30282, + 186055, + 357802, + 12492, + 577476, + 838, + 0, + 11, + 117602, + 0, + 187928, + 96860, + 4268, + 3478, + 818264, + 1649, + 17175, + 272, + 158951, + 440987, + 677594, + 14935, + 37953, + 0, + 198, + 160404, + 12, + 287803, + 2386, + 10, + 271663, + 319152, + 361322, + 68370, + 428, + 182707, + 387429, + 1152, + 360065, + 25218, + 2790, + 42228, + 13, + 110942, + 452491, + 1, + 665638, + 2308, + 1196, + 87306, + 66, + 219, + 0, + 130736, + 334, + 605, + 5979, + 2681, + 0, + 123463, + 11219, + 283681, + 19269, + 553, + 6217, + 130965, + 714409, + 242, + 674833, + 237581, + 133284, + 683, + 1758, + 278193, + 518726, + 44, + 420361, + 325228, + 14955, + 10, + 11994, + 64157, + 1937, + 20214, + 848, + 27804, + 151341, + 79236, + 316393, + 158883, + 1196, + 334, + 22797, + 185955, + 13857, + 397357, + 7948, + 6038, + 0, + 2621, + 16, + 155267, + 44809, + 9171, + 21328, + 12212, + 40200, + 2600, + 439, + 804014, + 10938, + 96135, + 43696, + 158715, + 4, + 284558, + 191, + 270254, + 7923, + 880603, + 21032, + 107700, + 172, + 700823, + 5613, + 78816, + 258290, + 214398, + 821856, + 295325, + 0, + 1, + 23559, + 63895, + 21249, + 717490, + 956952, + 944819, + 793, + 356, + 757716, + 111773, + 394826, + 25665, + 4358, + 640216, + 1152, + 37175, + 150192, + 106071, + 28992, + 67, + 1685, + 134242, + 2, + 102045, + 1457, + 419589, + 6789, + 677, + 94675, + 11300, + 2595, + 8, + 926535, + 265194, + 0, + 886048, + 246242, + 1494, + 191, + 169985, + 649765, + 0, + 201, + 1069, + 679163, + 16627, + 274639, + 84438, + 3, + 1301, + 247496, + 5879, + 710904, + 403652, + 958241, + 361, + 139732, + 6042, + 15985, + 2378, + 267031, + 223767, + 9656, + 241717, + 33863, + 14314, + 205697, + 1274, + 168000, + 621777, + 837913, + 89654, + 659829, + 69, + 503884, + 432717, + 70443, + 110891, + 19655, + 132432, + 620401, + 428, + 0, + 425662, + 0, + 0, + 0, + 194489, + 7601, + 26870, + 0, + 63, + 594, + 12278, + 582479, + 213723, + 424489, + 96446, + 990664, + 46966, + 44137, + 829810, + 104, + 19707, + 16, + 0, + 2499, + 167075, + 140972, + 249283, + 6620, + 68368, + 856414, + 9255, + 14315, + 0, + 11432, + 24329, + 216463, + 299556, + 818401, + 246607, + 697733, + 229, + 144, + 389394, + 664634, + 0, + 19393, + 657903, + 52912, + 952177, + 536931, + 187271, + 17687, + 970155, + 232571, + 234016, + 159980, + 13510, + 32952, + 0, + 0, + 24132, + 18806, + 15624, + 28364, + 472126, + 626978, + 599, + 112843, + 502933, + 915660, + 63920, + 0, + 84, + 10899, + 904823, + 126, + 469132, + 590052, + 195831, + 443113, + 294149, + 15944, + 2271, + 282974, + 211, + 0, + 22934, + 82283, + 49973, + 41707, + 87530, + 0, + 910528, + 0, + 36029, + 423337, + 817512, + 223671, + 27800, + 398847, + 198528, + 1, + 560679, + 518270, + 23033, + 501059, + 0, + 3909, + 272062, + 261581, + 187, + 52043, + 334, + 24354, + 3947, + 8549, + 37863, + 328851, + 963771, + 1, + 3930, + 82416, + 6, + 2943, + 122101, + 82577, + 85, + 89540, + 5135, + 109236, + 18297, + 1, + 177371, + 4541, + 769577, + 178, + 417, + 960566, + 33803, + 911651, + 248160, + 153725, + 43981, + 809174, + 116, + 486900, + 4842, + 148490, + 131534, + 4347, + 239949, + 984096, + 749756, + 429499, + 2794, + 78209, + 18812, + 21111, + 490, + 328042, + 12, + 132119, + 505103, + 353148, + 0, + 373656, + 951244, + 491, + 355778, + 30620, + 317, + 60175, + 220, + 214496, + 41249, + 5169, + 78367, + 506804, + 0, + 1368, + 407, + 295126, + 1288, + 86, + 97614, + 61640, + 244723, + 3, + 0, + 869827, + 527246, + 52, + 107036, + 240739, + 780281, + 113084, + 62009, + 740343, + 483201, + 8649, + 16419, + 1, + 801574, + 95524, + 326126, + 26912, + 877040, + 10262, + 5895, + 0, + 132633, + 59171, + 306347, + 702701, + 196245, + 12642, + 32723, + 24608, + 30287, + 45775, + 18281, + 7587, + 144532, + 5, + 35, + 99862, + 215127, + 170875, + 61461, + 77790, + 5, + 0, + 129358, + 0, + 105084, + 21399, + 42233, + 85397, + 480654, + 555988, + 89575, + 42346, + 20004, + 11102, + 21321, + 185, + 379267, + 849147, + 121514, + 3388, + 33662, + 12, + 164898, + 226, + 274, + 385003, + 365052, + 693376, + 41245, + 9010, + 41594, + 89835, + 10490, + 272, + 128437, + 0, + 122648, + 277, + 116505, + 38372, + 4, + 1376, + 0, + 46317, + 139368, + 36398, + 193899, + 30632, + 26371, + 7548, + 367643, + 954849, + 25889, + 36567, + 176, + 140631, + 4690, + 975031, + 80965, + 500471, + 8442, + 43, + 27758, + 301501, + 3797, + 80, + 384440, + 928477, + 4960, + 24566, + 33245, + 14638, + 228354, + 54347, + 861285, + 12841, + 2, + 157402, + 646747, + 53763, + 1, + 214732, + 49471, + 49757, + 998, + 201135, + 566, + 73512, + 194240, + 391773, + 21510, + 13, + 829894, + 783200, + 565329, + 2101, + 12, + 191043, + 1621, + 18443, + 279, + 294135, + 526503, + 729735, + 4639, + 444138, + 5835, + 12372, + 46362, + 1543, + 870907, + 83262, + 0, + 38331, + 95, + 1194, + 909, + 8053, + 453066, + 845561, + 411, + 3229, + 1, + 158, + 1431, + 835137, + 21774, + 7298, + 148388, + 224649, + 379318, + 520138, + 39781, + 172130, + 362634, + 487495, + 51957, + 158, + 1770, + 7, + 18010, + 1063, + 171484, + 19924, + 279867, + 469956, + 189785, + 0, + 814, + 60580, + 944349, + 18743, + 553235, + 0, + 95475, + 99, + 0, + 5, + 42623, + 178418, + 398940, + 5700, + 69023, + 5786, + 0, + 10531, + 551, + 86308, + 63451, + 32704, + 176903, + 0, + 251689, + 11589, + 25711, + 43437, + 1431, + 304, + 52965, + 34816, + 268688, + 47756, + 825323, + 122608, + 81246, + 69974, + 360515, + 99973, + 143015, + 5063, + 4499, + 34459, + 171982, + 677943, + 489082, + 257515, + 3765, + 5, + 7416, + 602206, + 74122, + 3, + 686204, + 5493, + 28901, + 11349, + 549668, + 257082, + 82000, + 17031, + 1517, + 7442, + 937160, + 722, + 0, + 72952, + 377192, + 438266, + 555, + 31436, + 284, + 56390, + 0, + 585856, + 27635, + 519344, + 126131, + 360273, + 845073, + 0, + 191965, + 55652, + 23, + 112773, + 639025, + 84749, + 0, + 330822, + 7173, + 126217, + 871, + 112112, + 0, + 664, + 530474, + 1, + 379564, + 172617, + 647308, + 0, + 356, + 17, + 84345, + 457, + 0, + 8, + 6, + 136602, + 634424, + 0, + 177298, + 100726, + 91661, + 383792, + 1665, + 43583, + 15775, + 4083, + 4277, + 345749, + 969599, + 65804, + 19327, + 0, + 352514, + 4225, + 9, + 103767, + 0, + 0, + 148436, + 850, + 33, + 2146, + 20153, + 50, + 9063, + 50329, + 348379, + 2569, + 83697, + 37073, + 715486, + 629, + 4753, + 442, + 259203, + 287223, + 48625, + 9, + 70184, + 45946, + 144947, + 0, + 60285, + 28640, + 7626, + 134159, + 33, + 12452, + 150566, + 348293, + 124426, + 353952, + 11, + 22, + 776742, + 29072, + 132168, + 254533, + 319957, + 1602, + 1659, + 209341, + 32847, + 92392, + 753005, + 1392, + 10271, + 28557, + 6717, + 941745, + 0, + 0, + 0, + 78645, + 45320, + 11193, + 1448, + 130626, + 377907, + 795535, + 24285, + 26094, + 266691, + 64449, + 77400, + 191410, + 1, + 1346, + 25224, + 489637, + 47052, + 248592, + 76689, + 0, + 7722, + 47285, + 3152, + 285577, + 0, + 149366, + 264346, + 1, + 208602, + 320459, + 131771, + 1421, + 350, + 723283, + 714934, + 0, + 566439, + 11656, + 34189, + 125484, + 943273, + 15, + 7789, + 0, + 7427, + 464278, + 680924, + 651102, + 87794, + 39640, + 838644, + 964500, + 1, + 1765, + 272604, + 10, + 837347, + 44845, + 130, + 163357, + 4150, + 403331, + 839132, + 44876, + 272792, + 592527, + 57225, + 128826, + 2915, + 2, + 3570, + 2410, + 199, + 171358, + 5931, + 53620, + 55299, + 1868, + 24123, + 165, + 346513, + 16527, + 133, + 517412, + 195700, + 730365, + 896209, + 152760, + 24577, + 65, + 8218, + 349642, + 901345, + 5127, + 5102, + 238318, + 955, + 631921, + 12218, + 55101, + 930381, + 219503, + 469237, + 132, + 16701, + 494, + 199729, + 0, + 32139, + 314, + 172, + 2947, + 106997, + 4871, + 236, + 6146, + 1843, + 128, + 0, + 254240, + 2964, + 14825, + 60624, + 2108, + 286953, + 654931, + 0, + 0, + 396587, + 19852, + 70311, + 363561, + 282, + 17966, + 924254, + 104173, + 130816, + 179096, + 105466, + 136, + 618261, + 358433, + 25587, + 49357, + 102, + 133746, + 620776, + 17084, + 406881, + 802675, + 349, + 69, + 8761, + 278482, + 16336, + 128, + 160096, + 25857, + 280, + 39639, + 726299, + 293905, + 4621, + 41, + 649, + 3655, + 269286, + 578026, + 0, + 11156, + 1, + 744858, + 531, + 48155, + 28435, + 7991, + 447, + 10201, + 379341, + 0, + 5773, + 0, + 295, + 228592, + 331155, + 104089, + 628069, + 29693, + 22, + 13, + 0, + 0, + 554349, + 6082, + 238, + 23, + 151873, + 805937, + 0, + 194076, + 6450, + 3, + 128322, + 69149, + 95511, + 86, + 844368, + 415964, + 51985, + 308686, + 553403, + 624943, + 365800, + 4, + 120263, + 91239, + 195248, + 58010, + 19, + 415112, + 136806, + 42, + 571848, + 55306, + 29454, + 3, + 144926, + 189, + 0, + 161943, + 592155, + 10930, + 279297, + 56932, + 957430, + 10244, + 190296, + 807209, + 781, + 1466, + 235055, + 33, + 196, + 58280, + 436, + 408649, + 221, + 711143, + 10495, + 2441, + 275720, + 2, + 15391, + 132107, + 102610, + 688549, + 237142, + 3041, + 14, + 308623, + 0, + 0, + 287, + 295147, + 61443, + 229, + 207, + 2051, + 64, + 13479, + 55656, + 570134, + 50387, + 225869, + 20615, + 258465, + 64932, + 112461, + 164521, + 907269, + 758563, + 22901, + 0, + 7944, + 48, + 154921, + 2784, + 548608, + 0, + 12524, + 142556, + 0, + 13882, + 507227, + 316598, + 987551, + 0, + 894687, + 1964, + 364, + 10316, + 440269, + 9, + 776723, + 72288, + 54604, + 185101, + 142, + 362, + 11679, + 77, + 79, + 529321, + 364, + 42387, + 0, + 570879, + 417503, + 604871, + 578806, + 1102, + 66584, + 615440, + 146744, + 19441, + 170478, + 144069, + 36170, + 145376, + 842283, + 193612, + 3, + 359429, + 368596, + 0, + 11064, + 7726, + 229410, + 63569, + 67402, + 91, + 203201, + 213513, + 0, + 704479, + 1325, + 0, + 385154, + 13, + 806763, + 197132, + 6183, + 45760, + 99377, + 0, + 972077, + 4043, + 195700, + 34229, + 0, + 154027, + 633, + 6, + 32142, + 0, + 29, + 620842, + 14099, + 495465, + 26937, + 0, + 0, + 432, + 227704, + 0, + 63, + 0, + 19, + 863491, + 20, + 1, + 160713, + 24607, + 85800, + 3566, + 37854, + 81913, + 121573, + 816, + 20, + 133253, + 692231, + 4869, + 255175, + 15028, + 9383, + 542877, + 4608, + 369610, + 243635, + 385285, + 391565, + 286009, + 0, + 61685, + 416318, + 208, + 67019, + 788416, + 88, + 165056, + 0, + 439589, + 160, + 105528, + 152, + 160624, + 865, + 390229, + 714086, + 6007, + 30229, + 481306, + 173266, + 1135, + 2266, + 8, + 59, + 104722, + 647885, + 579471, + 21309, + 230834, + 140278, + 31858, + 3288, + 36011, + 151387, + 594217, + 22439, + 418638, + 76859, + 29363, + 154809, + 275533, + 39, + 472996, + 22076, + 7481, + 155705, + 10406, + 214779, + 223, + 1312, + 16391, + 17203, + 55605, + 44579, + 69332, + 303, + 19217, + 26288, + 126212, + 316, + 98, + 114, + 37382, + 137591, + 439749, + 12972, + 54, + 154879, + 0, + 102680, + 7639, + 309119, + 263550, + 766, + 1124, + 56, + 686608, + 123767, + 518054, + 18, + 672385, + 3161, + 53791, + 26769, + 451670, + 61, + 148245, + 2713, + 96725, + 4794, + 33247, + 297946, + 33380, + 0, + 20034, + 5647, + 17227, + 76444, + 0, + 21011, + 675, + 13226, + 1027, + 990842, + 124459, + 34406, + 53, + 69540, + 134, + 0, + 168521, + 6, + 4075, + 1137, + 63740, + 220, + 10434, + 1171, + 28950, + 0, + 79680, + 993269, + 355622, + 15, + 0, + 1452, + 21667, + 22208, + 494484, + 33984, + 691308, + 10, + 693686, + 196, + 9, + 70676, + 157660, + 775, + 165, + 468432, + 1083, + 515154, + 778344, + 70241, + 42, + 40931, + 277125, + 43837, + 301881, + 1332, + 56712, + 9013, + 1299, + 7564, + 31092, + 1975, + 113517, + 833295, + 245021, + 36503, + 23586, + 149327, + 89175, + 10512, + 484348, + 187793, + 954609, + 53199, + 792175, + 126, + 12369, + 405, + 0, + 6614, + 322857, + 166, + 571874, + 60839, + 180975, + 146722, + 411565, + 1536, + 1, + 11, + 116230, + 60514, + 9003, + 2325, + 43763, + 63, + 355553, + 0, + 389876, + 14672, + 11526, + 160209, + 65, + 10283, + 966, + 10, + 58333, + 129920, + 2850, + 83346, + 0, + 14, + 295819, + 679550, + 143928, + 29489, + 82324, + 36558, + 267118, + 143313, + 90107, + 12789, + 951, + 0, + 187619, + 295317, + 82, + 41326, + 309682, + 907327, + 809358, + 324, + 139157, + 12, + 78366, + 671811, + 354, + 131, + 70525, + 35830, + 281018, + 91456, + 92523, + 54874, + 48273, + 2423, + 0, + 81, + 361314, + 374811, + 394758, + 15350, + 795, + 3, + 16779, + 796684, + 477556, + 73927, + 26643, + 119281, + 62692, + 17039, + 454778, + 952, + 48973, + 19529, + 151, + 239121, + 93509, + 254702, + 1307, + 10029, + 7973, + 546706, + 806644, + 680517, + 223, + 0, + 2, + 0, + 402421, + 619193, + 15685, + 2, + 939715, + 519198, + 0, + 444312, + 23204, + 35669, + 32467, + 0, + 799725, + 5883, + 2217, + 32292, + 355557, + 22179, + 1066, + 15704, + 610, + 37819, + 403626, + 83101, + 10989, + 311607, + 43394, + 72576, + 335450, + 85964, + 73734, + 105142, + 38292, + 0, + 181516, + 33959, + 611797, + 221838, + 5931, + 7666, + 1044, + 477173, + 13591, + 405, + 521, + 190653, + 184191, + 0, + 215, + 847195, + 22782, + 11912, + 27345, + 2572, + 0, + 566350, + 7, + 52302, + 26641, + 587826, + 127, + 2, + 44449, + 153198, + 14, + 926, + 285, + 0, + 938196, + 52255, + 9153, + 807, + 12548, + 358324, + 18521, + 104956, + 42738, + 116, + 135772, + 189554, + 38, + 54, + 36, + 89768, + 17170, + 75, + 34502, + 45489, + 172796, + 971810, + 16153, + 499280, + 1, + 879663, + 53830, + 186, + 539, + 242059, + 268, + 402, + 2732, + 68057, + 18463, + 198560, + 10068, + 591753, + 6116, + 699280, + 1, + 0, + 114258, + 277, + 149, + 283821, + 352561, + 88172, + 684476, + 3450, + 87, + 99936, + 3155, + 72983, + 31619, + 8832, + 58666, + 0, + 59023, + 306091, + 352150, + 255063, + 992708, + 23, + 4896, + 18165, + 424401, + 227613, + 5175, + 347, + 139846, + 11962, + 714, + 3501, + 82367, + 11110, + 10, + 12874, + 0, + 0, + 222712, + 169, + 123281, + 0, + 268149, + 101, + 17446, + 4262, + 489, + 0, + 30, + 0, + 277235, + 28, + 71, + 23, + 61219, + 953631, + 477548, + 662491, + 273, + 44787, + 4130, + 14483, + 470571, + 735977, + 406648, + 815898, + 5985, + 462696, + 937510, + 9, + 0, + 111727, + 93, + 331435, + 336402, + 78690, + 49, + 0, + 87422, + 1242, + 0, + 8783, + 8540, + 314, + 33411, + 805718, + 247, + 6870, + 523743, + 8323, + 612593, + 430, + 354048, + 264913, + 83, + 114063, + 202825, + 35202, + 32823, + 185554, + 85760, + 45159, + 5971, + 267733, + 4545, + 116, + 6910, + 24833, + 218, + 922362, + 221735, + 740, + 7112, + 31, + 15739, + 523589, + 4, + 95996, + 936, + 823951, + 0, + 88, + 160, + 375419, + 663627, + 3741, + 22896, + 114326, + 415962, + 880100, + 6222, + 18650, + 35524, + 195076, + 506, + 451640, + 541336, + 70903, + 3946, + 1, + 61765, + 1, + 2696, + 753129, + 289, + 225234, + 378692, + 1703, + 6751, + 1, + 820, + 7677, + 589, + 12412, + 317, + 69, + 226031, + 134523, + 318253, + 66677, + 111025, + 96, + 0, + 96, + 523528, + 1017, + 0, + 258740, + 420947, + 4600, + 400684, + 12174, + 11770, + 52, + 5959, + 82658, + 531787, + 202, + 548430, + 964, + 1054, + 34, + 96897, + 25445, + 47609, + 386052, + 97004, + 1935, + 30074, + 13458, + 494105, + 54, + 65575, + 594698, + 2340, + 20259, + 84, + 2774, + 534, + 972534, + 115057, + 0, + 11379, + 0, + 271, + 266305, + 132595, + 2, + 773561, + 52365, + 3585, + 351, + 148206, + 778964, + 149379, + 596, + 284914, + 2900, + 35596, + 1547, + 212027, + 8100, + 12248, + 3013, + 1814, + 183415, + 273633, + 15812, + 0, + 966680, + 14830, + 134309, + 0, + 416450, + 206611, + 816, + 82258, + 9873, + 3155, + 53485, + 779805, + 107690, + 254475, + 102504, + 72495, + 17301, + 472130, + 6895, + 245420, + 7299, + 110508, + 27776, + 246134, + 0, + 330853, + 0, + 271767, + 61886, + 24123, + 309681, + 58325, + 608865, + 20666, + 87349, + 229228, + 246, + 457768, + 5374, + 69643, + 148, + 618375, + 45236, + 352565, + 133904, + 152, + 10688, + 18, + 0, + 276036, + 493281, + 11156, + 12566, + 5762, + 113, + 24179, + 98, + 327, + 893, + 209180, + 140805, + 0, + 2341, + 66309, + 30305, + 630559, + 3682, + 152767, + 265822, + 142868, + 1535, + 728603, + 69081, + 353151, + 237995, + 1075, + 925071, + 86, + 6748, + 0, + 684186, + 735, + 13793, + 4790, + 73175, + 69677, + 367627, + 238650, + 303543, + 1, + 26059, + 21392, + 10, + 288609, + 0, + 76345, + 158496, + 7000, + 1865, + 20385, + 0, + 54213, + 9948, + 102667, + 6963, + 71, + 555744, + 5626, + 2512, + 1124, + 7171, + 628, + 29225, + 321687, + 61519, + 4, + 8352, + 9156, +}; + +char *pointers[NCYCLES]; + +int main(void) +{ + int r, i, j, sp, sq; + char *p, *q, *ep, *eq; + int ok; + int err = 0; + + for ( r = 0 ; r < 4 ; r++ ) { + for ( i = 0 ; i < NCYCLES ; i++ ) { + pointers[i] = p = malloc(sp = sizes[i]); + ep = p+sp; + ok = 1; + for ( j = 0 ; j < i ; j++ ) { + q = pointers[j]; + sq = sizes[j]; + eq = q+sq; + + if ( (p < q && ep > q) || (p >= q && p < eq) ) { + ok = 0; + err = 1; + break; + } + } + printf("Allocated %6d bytes at %p, ok = %d\n", sp, p, ok); + + if ( p ) + memset(p, 0xee, sp); /* Poison this memory */ + } + + for ( i = 0 ; i < NCYCLES ; i++ ) { + free(pointers[i]); + printf("Freed %6d bytes at %p\n", sizes[i], pointers[i]); + } + } + + return err; +} + diff --git a/klibc/klibc/tests/memstrtest.c b/klibc/klibc/tests/memstrtest.c new file mode 100644 index 0000000000..14d5173cb2 --- /dev/null +++ b/klibc/klibc/tests/memstrtest.c @@ -0,0 +1,29 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +int main(void) +{ + unsigned char t1[256], t2[256]; + int i; + int r; + + for(i = 0; i < sizeof(t1); i++) + t1[i] = t2[i] = (unsigned char)i; + + r = memcmp(t1, t2, sizeof(t1)); + printf("memcmp r = %d\n", r); + r = memcmp(t1, t2, sizeof(t1)/2); + printf("memcmp r = %d\n", r); + t1[255] = 0; + r = memcmp(t1, t2, sizeof(t1)); + printf("memcmp r = %d\n", r); + + for (i = 0; i < sizeof(t1); i++) + t1[i] = 0xaa; + memset(t2, 0xaa, sizeof(t2)); + r = memcmp(t1, t2, sizeof(t1)); + printf("memcmp r = %d\n", r); + return 0; +} + diff --git a/klibc/klibc/tests/microhello.c b/klibc/klibc/tests/microhello.c new file mode 100644 index 0000000000..e57cd05a50 --- /dev/null +++ b/klibc/klibc/tests/microhello.c @@ -0,0 +1,9 @@ +#include <stdio.h> +#include <unistd.h> + +int main(void) +{ + const char hello[] = "Hello, World!\n"; + _fwrite(hello, sizeof hello-1, stdout); + return 0; +} diff --git a/klibc/klibc/tests/minihello.c b/klibc/klibc/tests/minihello.c new file mode 100644 index 0000000000..7698e0666b --- /dev/null +++ b/klibc/klibc/tests/minihello.c @@ -0,0 +1,7 @@ +#include <stdio.h> + +int main(void) +{ + fputs("Hello, World!\n", stdout); + return 0; +} diff --git a/klibc/klibc/tests/minips.c b/klibc/klibc/tests/minips.c new file mode 100644 index 0000000000..c599150858 --- /dev/null +++ b/klibc/klibc/tests/minips.c @@ -0,0 +1,452 @@ +/* + * Copyright 1998 by Albert Cahalan; all rights reserved. + * This file may be used subject to the terms and conditions of the + * GNU Library General Public License Version 2, or any later version + * at your option, as published by the Free Software Foundation. + * This program 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 Library General Public License for more details. + */ + +/* This is a minimal /bin/ps, designed to be smaller than the old ps + * while still supporting some of the more important features of the + * new ps. (for total size, note that this ps does not need libproc) + * It is suitable for Linux-on-a-floppy systems only. + * + * Maintainers: do not compile or install for normal systems. + * Anyone needing this will want to tweak their compiler anyway. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <unistd.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <dirent.h> + +#include <asm/param.h> /* HZ */ +#include <asm/page.h> /* PAGE_SIZE */ + +static int P_euid; +static int P_pid; +static char P_cmd[16]; +static char P_state; +static int P_ppid, P_pgrp, P_session, P_tty, P_tpgid; +static unsigned long P_flags, P_min_flt, P_cmin_flt, P_maj_flt, P_cmaj_flt, P_utime, P_stime; +static long P_cutime, P_cstime, P_priority, P_nice, P_timeout, P_it_real_value; +static unsigned long P_start_time, P_vsize; +static long P_rss; +static unsigned long P_rss_rlim, P_start_code, P_end_code, P_start_stack, P_kstk_esp, P_kstk_eip; +static unsigned P_signal, P_blocked, P_sigignore, P_sigcatch; +static unsigned long P_wchan, P_nswap, P_cnswap; + + +#if 0 +static int screen_cols = 80; +static int w_count; +#endif + +static int want_one_pid; +static const char *want_one_command; +static int select_notty; +static int select_all; + +static int ps_format; +static int old_h_option; + +/* we only pretend to support this */ +static int show_args; /* implicit with -f and all BSD options */ +static int bsd_c_option; /* this option overrides the above */ + +static int ps_argc; /* global argc */ +static char **ps_argv; /* global argv */ +static int thisarg; /* index into ps_argv */ +static char *flagptr; /* current location in ps_argv[thisarg] */ + + +#ifndef PAGE_SIZE +#warning PAGE_SIZE not defined, assuming it is 4096 +#define PAGE_SIZE 4096 +#endif + +#ifndef HZ +#warning HZ not defined, assuming it is 100 +#define HZ 100 +#endif + + + +static void usage(void){ + fprintf(stderr, + "-C select by command name (minimal ps only accepts one)\n" + "-p select by process ID (minimal ps only accepts one)\n" + "-e all processes (same as ax)\n" + "a all processes w/ tty, including other users\n" + "x processes w/o controlling ttys\n" + "-f full format\n" + "-j,j job control format\n" + "v virtual memory format\n" + "-l,l long format\n" + "u user-oriented format\n" + "-o user-defined format (limited support, only \"ps -o pid=\")\n" + "h no header\n" +/* + "-A all processes (same as ax)\n" + "c true command name\n" + "-w,w wide output\n" +*/ + ); + exit(1); +} + +/* + * Return the next argument, or call the usage function. + * This handles both: -oFOO -o FOO + */ +static const char *get_opt_arg(void){ + const char *ret; + ret = flagptr+1; /* assume argument is part of ps_argv[thisarg] */ + if(*ret) return ret; + if(++thisarg >= ps_argc) usage(); /* there is nothing left */ + /* argument is the new ps_argv[thisarg] */ + ret = ps_argv[thisarg]; + if(!ret || !*ret) usage(); + return ret; +} + + +/* return the PID, or 0 if nothing good */ +static void parse_pid(const char *str){ + char *endp; + int num; + if(!str) goto bad; + num = strtol(str, &endp, 0); + if(*endp != '\0') goto bad; + if(num<1) goto bad; + if(want_one_pid) goto bad; + want_one_pid = num; + return; +bad: + usage(); +} + +/***************** parse SysV options, including Unix98 *****************/ +static void parse_sysv_option(void){ + do{ + switch(*flagptr){ + /**** selection ****/ + case 'C': /* end */ + if(want_one_command) usage(); + want_one_command = get_opt_arg(); + return; /* can't have any more options */ + case 'p': /* end */ + parse_pid(get_opt_arg()); + return; /* can't have any more options */ + case 'A': + case 'e': + select_all++; + select_notty++; +case 'w': /* here for now, since the real one is not used */ + break; + /**** output format ****/ + case 'f': + show_args = 1; + /* FALL THROUGH */ + case 'j': + case 'l': + if(ps_format) usage(); + ps_format = *flagptr; + break; + case 'o': /* end */ + /* We only support a limited form: "ps -o pid=" (yes, just "pid=") */ + if(strcmp(get_opt_arg(),"pid=")) usage(); + if(ps_format) usage(); + ps_format = 'o'; + old_h_option++; + return; /* can't have any more options */ + /**** other stuff ****/ +#if 0 + case 'w': + w_count++; + break; +#endif + default: + usage(); + } /* switch */ + }while(*++flagptr); +} + +/************************* parse BSD options **********************/ +static void parse_bsd_option(void){ + do{ + switch(*flagptr){ + /**** selection ****/ + case 'a': + select_all++; + break; + case 'x': + select_notty++; + break; + case 'p': /* end */ + parse_pid(get_opt_arg()); + return; /* can't have any more options */ + /**** output format ****/ + case 'j': + case 'l': + case 'u': + case 'v': + if(ps_format) usage(); + ps_format = 0x80 | *flagptr; /* use 0x80 to tell BSD from SysV */ + break; + /**** other stuff ****/ + case 'c': + bsd_c_option++; +#if 0 + break; +#endif + case 'w': +#if 0 + w_count++; +#endif + break; + case 'h': + old_h_option++; + break; + default: + usage(); + } /* switch */ + }while(*++flagptr); +} + +#if 0 +/* not used yet */ +static void choose_dimensions(void){ + struct winsize ws; + char *columns; + /* screen_cols is 80 by default */ + if(ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col>30) screen_cols = ws.ws_col; + columns = getenv("COLUMNS"); + if(columns && *columns){ + long t; + char *endptr; + t = strtol(columns, &endptr, 0); + if(!*endptr && (t>30) && (t<(long)999999999)) screen_cols = (int)t; + } + if(w_count && (screen_cols<132)) screen_cols=132; + if(w_count>1) screen_cols=999999999; +} +#endif + +static void arg_parse(int argc, char *argv[]){ + int sel = 0; /* to verify option sanity */ + ps_argc = argc; + ps_argv = argv; + thisarg = 0; + /**** iterate over the args ****/ + while(++thisarg < ps_argc){ + flagptr = ps_argv[thisarg]; + switch(*flagptr){ + case '0' ... '9': + show_args = 1; + parse_pid(flagptr); + break; + case '-': + flagptr++; + parse_sysv_option(); + break; + default: + show_args = 1; + parse_bsd_option(); + break; + } + } + /**** sanity check and clean-up ****/ + if(want_one_pid) sel++; + if(want_one_command) sel++; + if(select_notty || select_all) sel++; + if(sel>1 || select_notty>1 || select_all>1 || bsd_c_option>1 || old_h_option>1) usage(); + if(bsd_c_option) show_args = 0; +} + +/* return 1 if it works, or 0 for failure */ +static int stat2proc(int pid) { + char buf[800]; /* about 40 fields, 64-bit decimal is about 20 chars */ + int num; + int fd; + char* tmp; + struct stat sb; /* stat() used to get EUID */ + snprintf(buf, 32, "/proc/%d/stat", pid); + if ( (fd = open(buf, O_RDONLY, 0) ) == -1 ) return 0; + num = read(fd, buf, sizeof buf - 1); + fstat(fd, &sb); + P_euid = sb.st_uid; + close(fd); + if(num<80) return 0; + buf[num] = '\0'; + tmp = strrchr(buf, ')'); /* split into "PID (cmd" and "<rest>" */ + *tmp = '\0'; /* replace trailing ')' with NUL */ + /* parse these two strings separately, skipping the leading "(". */ + memset(P_cmd, 0, sizeof P_cmd); /* clear */ + sscanf(buf, "%d (%15c", &P_pid, P_cmd); /* comm[16] in kernel */ + num = sscanf(tmp + 2, /* skip space after ')' too */ + "%c " + "%d %d %d %d %d " + "%lu %lu %lu %lu %lu %lu %lu " + "%ld %ld %ld %ld %ld %ld " + "%lu %lu " + "%ld " + "%lu %lu %lu %lu %lu %lu " + "%u %u %u %u " /* no use for RT signals */ + "%lu %lu %lu", + &P_state, + &P_ppid, &P_pgrp, &P_session, &P_tty, &P_tpgid, + &P_flags, &P_min_flt, &P_cmin_flt, &P_maj_flt, &P_cmaj_flt, &P_utime, &P_stime, + &P_cutime, &P_cstime, &P_priority, &P_nice, &P_timeout, &P_it_real_value, + &P_start_time, &P_vsize, + &P_rss, + &P_rss_rlim, &P_start_code, &P_end_code, &P_start_stack, &P_kstk_esp, &P_kstk_eip, + &P_signal, &P_blocked, &P_sigignore, &P_sigcatch, + &P_wchan, &P_nswap, &P_cnswap + ); +/* fprintf(stderr, "stat2proc converted %d fields.\n",num); */ + P_vsize /= 1024; + P_rss *= (PAGE_SIZE/1024); + if(num < 30) return 0; + if(P_pid != pid) return 0; + return 1; +} + +static const char *do_time(unsigned long t){ + int hh,mm,ss; + static char buf[32]; + int cnt = 0; + t /= HZ; + ss = t%60; + t /= 60; + mm = t%60; + t /= 60; + hh = t%24; + t /= 24; + if(t) cnt = snprintf(buf, sizeof buf, "%d-", (int)t); + snprintf(cnt + buf, sizeof(buf)-cnt, "%02d:%02d:%02d", hh, mm, ss); + return buf; +} + +static void print_proc(void){ + char tty[16]; + snprintf(tty, sizeof tty, "%3d,%-3d", (P_tty>>8)&0xff, P_tty&0xff); + switch(ps_format){ + case 0: + printf("%5d %s %s", P_pid, tty, do_time(P_utime+P_stime)); + break; + case 'o': + printf("%d\n", P_pid); + return; /* don't want the command */ + case 'l': + printf( + "%03x %c %5d %5d %5d - %3d %3d - " + "%5ld %06x %s %s", + (unsigned)P_flags&0x777, P_state, P_euid, P_pid, P_ppid, + (int)P_priority, (int)P_nice, P_vsize/(PAGE_SIZE/1024), + (unsigned)(P_wchan&0xffffff), tty, do_time(P_utime+P_stime) + ); + break; + case 'f': + printf( + "%5d %5d %5d - - %s %s", + P_euid, P_pid, P_ppid, tty, do_time(P_utime+P_stime) + ); + break; + case 'j': + printf( + "%5d %5d %5d %s %s", + P_pid, P_pgrp, P_session, tty, do_time(P_utime+P_stime) + ); + break; + case 'u'|0x80: + printf( + "%5d %5d - - %5ld %5ld %s %c - %s", + P_euid, P_pid, P_vsize, P_rss, tty, P_state, + do_time(P_utime+P_stime) + ); + break; + case 'v'|0x80: + printf( + "%5d %s %c %s %6d - - %5d -", + P_pid, tty, P_state, do_time(P_utime+P_stime), (int)P_maj_flt, + (int)P_rss + ); + break; + case 'j'|0x80: + printf( + "%5d %5d %5d %5d %s %5d %c %5d %s", + P_ppid, P_pid, P_pgrp, P_session, tty, P_tpgid, P_state, P_euid, do_time(P_utime+P_stime) + ); + break; + case 'l'|0x80: + printf( + "%03x %5d %5d %5d %3d %3d " + "%5ld %4ld %06x %c %s %s", + (unsigned)P_flags&0x777, P_euid, P_pid, P_ppid, (int)P_priority, (int)P_nice, + P_vsize, P_rss, (unsigned)(P_wchan&0xffffff), P_state, tty, do_time(P_utime+P_stime) + ); + break; + default: + } + if(show_args) printf(" [%s]\n", P_cmd); + else printf(" %s\n", P_cmd); +} + + +int main(int argc, char *argv[]){ + arg_parse(argc, argv); +#if 0 + choose_dimensions(); +#endif + if(!old_h_option){ + const char *head; + switch(ps_format){ + default: /* can't happen */ + case 0: head = " PID TTY TIME CMD"; break; + case 'l': head = " F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD"; break; + case 'f': head = " UID PID PPID C STIME TTY TIME CMD"; break; + case 'j': head = " PID PGID SID TTY TIME CMD"; break; + case 'u'|0x80: head = " UID PID %CPU %MEM VSZ RSS TTY S START TIME COMMAND"; break; + case 'v'|0x80: head = " PID TTY S TIME MAJFL TRS DRS RSS %MEM COMMAND"; break; + case 'j'|0x80: head = " PPID PID PGID SID TTY TPGID S UID TIME COMMAND"; break; + case 'l'|0x80: head = " F UID PID PPID PRI NI VSZ RSS WCHAN S TTY TIME COMMAND"; break; + } + printf("%s\n",head); + } + if(want_one_pid){ + if(stat2proc(want_one_pid)) print_proc(); + else exit(1); + }else{ + struct dirent *ent; /* dirent handle */ + DIR *dir; + int ouruid; + int found_a_proc; + found_a_proc = 0; + ouruid = getuid(); + dir = opendir("/proc"); + while(( ent = readdir(dir) )){ + if(*ent->d_name<'0' || *ent->d_name>'9') continue; + if(!stat2proc(atoi(ent->d_name))) continue; + if(want_one_command){ + if(strcmp(want_one_command,P_cmd)) continue; + }else{ + if(!select_notty && P_tty==-1) continue; + if(!select_all && P_euid!=ouruid) continue; + } + found_a_proc++; + print_proc(); + } + closedir(dir); + exit(!found_a_proc); + } + return 0; +} diff --git a/klibc/klibc/tests/nfs_no_rpc.c b/klibc/klibc/tests/nfs_no_rpc.c new file mode 100644 index 0000000000..11b9f61fea --- /dev/null +++ b/klibc/klibc/tests/nfs_no_rpc.c @@ -0,0 +1,538 @@ +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/utsname.h> +#include <sys/mount.h> +#include <netinet/in.h> +#include <unistd.h> +#include <signal.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +/* Default path we try to mount. "%s" gets replaced by our IP address */ +#define NFS_ROOT "/tftpboot/%s" +#define NFS_DEF_FILE_IO_BUFFER_SIZE 4096 +#define NFS_MAXPATHLEN 1024 +#define NFS_MNT_PROGRAM 100005 +#define NFS_MNT_PORT 627 +#define NFS_PROGRAM 100003 +#define NFS_PORT 2049 +#define NFS2_VERSION 2 +#define NFS3_VERSION 3 +#define NFS_MNT_PROGRAM 100005 +#define NFS_MNT_VERSION 1 +#define NFS_MNT3_VERSION 3 +#define MNTPROC_MNT 1 +#define MOUNTPROC3_MNT 1 +#define RPC_PMAP_PROGRAM 100000 +#define RPC_PMAP_VERSION 2 +#define RPC_PMAP_PORT 111 + +#define NFS2_FHSIZE 32 +#define NFS3_FHSIZE 64 + +#define RPC_VERSION 2 + +enum rpc_msg_type { + RPC_CALL = 0, + RPC_REPLY = 1 +}; + +enum rpc_auth_flavor { + RPC_AUTH_NULL = 0, + RPC_AUTH_UNIX = 1, + RPC_AUTH_SHORT = 2, + RPC_AUTH_DES = 3, + RPC_AUTH_KRB = 4, +}; + +enum rpc_reply_stat { + RPC_MSG_ACCEPTED = 0, + RPC_MSG_DENIED = 1 +}; + +#define NFS_MAXFHSIZE 64 +struct nfs_fh { + unsigned short size; + unsigned char data[NFS_MAXFHSIZE]; +}; + +struct nfs2_fh { + char data[NFS2_FHSIZE]; +}; + +#define NFS_MOUNT_VERSION 4 + +struct nfs_mount_data { + int version; + int fd; + struct nfs2_fh old_root; + int flags; + int rsize; + int wsize; + int timeo; + int retrans; + int acregmin; + int acregmax; + int acdirmin; + int acdirmax; + struct sockaddr_in addr; + char hostname[256]; + int namlen; + unsigned int bsize; + struct nfs_fh root; +}; + +#define NFS_MOUNT_SOFT 0x0001 /* 1 */ +#define NFS_MOUNT_INTR 0x0002 /* 1 */ +#define NFS_MOUNT_SECURE 0x0004 /* 1 */ +#define NFS_MOUNT_POSIX 0x0008 /* 1 */ +#define NFS_MOUNT_NOCTO 0x0010 /* 1 */ +#define NFS_MOUNT_NOAC 0x0020 /* 1 */ +#define NFS_MOUNT_TCP 0x0040 /* 2 */ +#define NFS_MOUNT_VER3 0x0080 /* 3 */ +#define NFS_MOUNT_KERBEROS 0x0100 /* 3 */ +#define NFS_MOUNT_NONLM 0x0200 /* 3 */ +#define NFS_MOUNT_BROKEN_SUID 0x0400 /* 4 */ +#define NFS_MOUNT_FLAGMASK 0xFFFF + +static char nfs_root_name[256]; +static u_int32_t root_server_addr; +static char root_server_path[256]; + +/* Address of NFS server */ +static u_int32_t servaddr; + +/* Name of directory to mount */ +static char nfs_path[NFS_MAXPATHLEN]; + +/* NFS-related data */ +static struct nfs_mount_data nfs_data = { + .version = NFS_MOUNT_VERSION, + .flags = NFS_MOUNT_NONLM, /* No lockd in nfs root yet */ + .rsize = NFS_DEF_FILE_IO_BUFFER_SIZE, + .wsize = NFS_DEF_FILE_IO_BUFFER_SIZE, + .bsize = 0, + .timeo = 7, + .retrans = 3, + .acregmin = 3, + .acregmax = 60, + .acdirmin = 30, + .acdirmax = 60, +}; +static int nfs_port = -1; +static int mount_port; + +/*************************************************************************** + + Parsing of options + + ***************************************************************************/ + +/* + * The following integer options are recognized + */ +static struct nfs_int_opts { + const char *name; + int *val; +} root_int_opts[] = { + { "port", &nfs_port }, + { "rsize", &nfs_data.rsize }, + { "wsize", &nfs_data.wsize }, + { "timeo", &nfs_data.timeo }, + { "retrans", &nfs_data.retrans }, + { "acregmin", &nfs_data.acregmin }, + { "acregmax", &nfs_data.acregmax }, + { "acdirmin", &nfs_data.acdirmin }, + { "acdirmax", &nfs_data.acdirmax }, + { NULL, NULL } +}; + +/* + * And now the flag options + */ +static struct nfs_bool_opts { + const char *name; + int and_mask; + int or_mask; +} root_bool_opts[] = { + { "soft", ~NFS_MOUNT_SOFT, NFS_MOUNT_SOFT }, + { "hard", ~NFS_MOUNT_SOFT, 0 }, + { "intr", ~NFS_MOUNT_INTR, NFS_MOUNT_INTR }, + { "nointr", ~NFS_MOUNT_INTR, 0 }, + { "posix", ~NFS_MOUNT_POSIX, NFS_MOUNT_POSIX }, + { "noposix", ~NFS_MOUNT_POSIX, 0 }, + { "cto", ~NFS_MOUNT_NOCTO, 0 }, + { "nocto", ~NFS_MOUNT_NOCTO, NFS_MOUNT_NOCTO }, + { "ac", ~NFS_MOUNT_NOAC, 0 }, + { "noac", ~NFS_MOUNT_NOAC, NFS_MOUNT_NOAC }, + { "lock", ~NFS_MOUNT_NONLM, 0 }, + { "nolock", ~NFS_MOUNT_NONLM, NFS_MOUNT_NONLM }, +#ifdef CONFIG_NFS_V3 + { "v2", ~NFS_MOUNT_VER3, 0 }, + { "v3", ~NFS_MOUNT_VER3, NFS_MOUNT_VER3 }, +#endif + { "udp", ~NFS_MOUNT_TCP, 0 }, + { "tcp", ~NFS_MOUNT_TCP, NFS_MOUNT_TCP }, + { "broken_suid",~NFS_MOUNT_BROKEN_SUID, NFS_MOUNT_BROKEN_SUID }, + { NULL, 0, 0 } +}; +/* + * Parse option string. + */ +static void root_nfs_parse(char *name, char *buf) +{ + char *options, *val, *cp; + + if ((options = strchr(name, ','))) { + *options++ = 0; + cp = strtok(options, ","); + while (cp) { + if ((val = strchr(cp, '='))) { + struct nfs_int_opts *opts = root_int_opts; + *val++ = '\0'; + while (opts->name && strcmp(opts->name, cp)) + opts++; + if (opts->name) + *(opts->val) = (int) strtoul(val, NULL, 10); + } else { + struct nfs_bool_opts *opts = root_bool_opts; + while (opts->name && strcmp(opts->name, cp)) + opts++; + if (opts->name) { + nfs_data.flags &= opts->and_mask; + nfs_data.flags |= opts->or_mask; + } + } + cp = strtok(NULL, ","); + } + } + if (name[0] && strcmp(name, "default")) { + strncpy(buf, name, NFS_MAXPATHLEN-1); + buf[NFS_MAXPATHLEN-1] = 0; + } +} + +/* + * Prepare the NFS data structure and parse all options. + */ +static int root_nfs_name(char *name) +{ + char buf[NFS_MAXPATHLEN]; + struct utsname uname_buf; + + /* Set some default values */ + strcpy(buf, NFS_ROOT); + + /* Process options received from the remote server */ + root_nfs_parse(root_server_path, buf); + + /* Override them by options set on kernel command-line */ + root_nfs_parse(name, buf); + + uname(&uname_buf); + if (strlen(buf) + strlen(uname_buf.nodename) > NFS_MAXPATHLEN) { + printf("nfsroot: Pathname for remote directory too long.\n"); + return -1; + } + sprintf(nfs_path, buf, uname_buf.nodename); + + return 1; +} + +/*************************************************************************** + + Routines to actually mount the root directory + + ***************************************************************************/ + +/* + * Construct sockaddr_in from address and port number. + */ +static inline void +set_sockaddr(struct sockaddr_in *sin, u_int32_t addr, u_int16_t port) +{ + memset(sin, 0, sizeof(*sin)); + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = addr; + sin->sin_port = port; +} + +/* + * Extremely crude RPC-over-UDP call. We get an already encoded request + * to pass, we do that and put the reply into buffer. That (and callers + * below - getport, getfh2 and getfh3) should be replaced with proper + * librpc use. Now, if we only had one that wasn't bloated as a dead + * gnu that had lied for a while under the sun... + */ + +static u_int32_t XID; +static int flag; +static void timeout(int n) +{ + (void)n; + flag = 1; +} +static int do_call(struct sockaddr_in *sin, u_int32_t msg[], u_int32_t rmsg[], + u_int32_t len, u_int32_t rlen) +{ + struct sockaddr_in from; + int slen = sizeof(struct sockaddr_in); + struct timeval tv = {1, 0}; + int n; + int fd; + + signal(SIGALRM, timeout); + fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (fd < 0) + goto Esocket; + setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (void*)&tv, sizeof(tv)); + len *= 4; + if (sendto(fd, msg, len, 0, (struct sockaddr *)sin, slen)!=(int)len) + goto Esend; + setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (void*)&tv, sizeof(tv)); + alarm(0); + flag = 0; + alarm(5); + rlen *= 4; + do { + slen = sizeof(from); + n = recvfrom(fd, rmsg, rlen, 0, (struct sockaddr*)&from, &slen); + if (flag || n < 0) + goto Erecv; + } while (memcmp(&from, sin, sizeof(from)) || rmsg[0] != msg[0]); + + if (n < 6*4 || n % 4 || ntohl(rmsg[1]) != 1 || rmsg[2] || + rmsg[3] || rmsg[4] || rmsg[5]) + goto Einval; + alarm(0); + close(fd); + return n / 4 - 6; + +Esend: printf("rpc: write failed\n"); + goto out; +Erecv: printf("rpc: read failed\n"); + goto out; +Einval: printf("rpc: invalid response\n"); + goto out; +Esocket:printf("rpc: can't create socket\n"); + return -1; +out: + alarm(0); + close(fd); + return -1; +} + +enum { + PMAP_GETPORT = 3 +}; + +static void do_header(u_int32_t msg[], u_int32_t prog, u_int32_t vers, u_int32_t proc) +{ + msg[0] = XID++; + msg[1] = htonl(RPC_CALL); + msg[2] = htonl(RPC_VERSION); + msg[3] = htonl(prog); + msg[4] = htonl(vers); + msg[5] = htonl(proc); + msg[6] = htonl(RPC_AUTH_NULL); + msg[7] = htonl(0); + msg[8] = htonl(RPC_AUTH_NULL); + msg[9] = htonl(0); +} + +static int getport(u_int32_t prog, u_int32_t vers, u_int32_t prot) +{ + struct sockaddr_in sin; + unsigned msg[14]; + unsigned rmsg[7]; + int n; + set_sockaddr(&sin, servaddr, htons(RPC_PMAP_PORT)); + do_header(msg, RPC_PMAP_PROGRAM, RPC_PMAP_VERSION, PMAP_GETPORT); + msg[10] = htonl(prog); + msg[11] = htonl(vers); + msg[12] = htonl(prot); + msg[13] = htonl(0); + n = do_call(&sin, msg, rmsg, 14, 7); + if (n <= 0) + return -1; + else + return ntohl(rmsg[6]); +} + +static int getfh2(void) +{ + struct sockaddr_in sin; + unsigned msg[10+1+256/4]; + unsigned rmsg[6 + 1 + NFS2_FHSIZE/4]; + int n; + int len = strlen(nfs_path); + set_sockaddr(&sin, servaddr, mount_port); + + if (len > 255) { + printf("nfsroot: pathname is too long"); + return -1; + } + memset(msg, 0, sizeof(msg)); + do_header(msg, NFS_MNT_PROGRAM, NFS_MNT_VERSION, MNTPROC_MNT); + msg[10] = htonl(len); + strcpy((char*)&msg[11], nfs_path); + n = do_call(&sin, msg, rmsg, 11 + (len + 3)/4, 7 + NFS2_FHSIZE/4); + if (n < 0) + return -1; + if (n != NFS2_FHSIZE/4 + 1) + goto Esize; + if (rmsg[6]) { + printf("nfsroot: mountd returned an error (%d)",htonl(rmsg[6])); + return -1; + } + nfs_data.root.size = NFS2_FHSIZE; + memcpy(nfs_data.root.data, &rmsg[7], NFS2_FHSIZE); + return 0; +Esize: + printf("nfsroot: bad fhandle size"); + return -1; +} + +static int getfh3(void) +{ + struct sockaddr_in sin; + unsigned msg[10+1+256/4]; + unsigned rmsg[6 + 1 + 1 + NFS3_FHSIZE/4]; + int n; + int len = strlen(nfs_path); + int size; + set_sockaddr(&sin, servaddr, mount_port); + + if (len > 255) { + printf("nfsroot: pathname is too long"); + return -1; + } + memset(msg, 0, sizeof(msg)); + do_header(msg, NFS_MNT_PROGRAM, NFS_MNT3_VERSION, MOUNTPROC3_MNT); + msg[10] = htonl(len); + strcpy((char*)&msg[11], nfs_path); + n = do_call(&sin, msg, rmsg, 11 + (len + 3)/4, 8 + NFS3_FHSIZE/4); + if (n < 0) + return -1; + if (n <= 2) + goto Esize; + if (rmsg[6]) { + printf("nfsroot: mountd returned an error (%d)",htonl(rmsg[6])); + return -1; + } + size = ntohl(rmsg[7]); + if (size > NFS3_FHSIZE || n != 2 + size/4) + goto Esize; + nfs_data.root.size = size; + memcpy(nfs_data.root.data, &rmsg[8], size); + return 0; +Esize: + printf("nfsroot: bad fhandle size"); + return -1; +} + +/* + * Use portmapper to find mountd and nfsd port numbers if not overriden + * by the user. Use defaults if portmapper is not available. + * XXX: Is there any nfs server with no portmapper? + */ +static int root_nfs_ports(void) +{ + int port; + int nfsd_ver, mountd_ver; + int proto; + + if (nfs_data.flags & NFS_MOUNT_VER3) { + nfsd_ver = NFS3_VERSION; + mountd_ver = NFS_MNT3_VERSION; + } else { + nfsd_ver = NFS2_VERSION; + mountd_ver = NFS_MNT_VERSION; + } + + proto = (nfs_data.flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP; + + if (nfs_port < 0) { + if ((port = getport(NFS_PROGRAM, nfsd_ver, proto)) < 0) { + printf("nfsroot: Unable to get nfsd port " + "number from server, using default\n"); + port = NFS_PORT; + } + nfs_port = htons(port); + printf("nfsroot: Portmapper on server returned %d " + "as nfsd port\n", port); + } + + if ((port = getport(NFS_MNT_PROGRAM, mountd_ver, proto)) < 0) { + printf("nfsroot: Unable to get mountd port " + "number from server, using default\n"); + port = NFS_MNT_PORT; + } + mount_port = htons(port); + printf("nfsroot: mountd port is %d\n", port); + + return 0; +} + +int main(void) +{ + unsigned char *p; + struct timeval tv; + char *s; + + /* FIX: use getopt() instead of this */ + + s = getenv("root_server_addr"); + if (s) + root_server_addr = strtoul(s, NULL, 10); + s = getenv("root_server_path"); + if (s) + strncpy(root_server_path, s, 255); + s = getenv("nfs_root_name"); + if (s) + strncpy(nfs_root_name, s, 255); + + /* + * Decode the root directory path name and NFS options from + * the kernel command line. This has to go here in order to + * be able to use the client IP address for the remote root + * directory (necessary for pure RARP booting). + */ + if (root_nfs_name(nfs_root_name) < 0) + return 0; + if ((servaddr = root_server_addr) == INADDR_NONE) { + printf("nfsroot: No NFS server available, giving up.\n"); + return 0; + } + + p = (char *) &servaddr; + sprintf(nfs_data.hostname, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); + +#ifdef NFSROOT_DEBUG + printf("nfsroot: Mounting %s on server %s as root\n", + nfs_path, nfs_data.hostname); + printf("nfsroot: rsize = %d, wsize = %d, timeo = %d, retrans = %d\n", + nfs_data.rsize, nfs_data.wsize, nfs_data.timeo, nfs_data.retrans); + printf("nfsroot: acreg (min,max) = (%d,%d), acdir (min,max) = (%d,%d)\n", + nfs_data.acregmin, nfs_data.acregmax, + nfs_data.acdirmin, nfs_data.acdirmax); + printf("nfsroot: nfsd port = %d, mountd port = %d, flags = %08x\n", + nfs_port, mount_port, nfs_data.flags); +#endif + + gettimeofday(&tv, NULL); + XID = (tv.tv_sec << 15) ^ tv.tv_usec; + + if (root_nfs_ports() < 0) + return 0; + if (nfs_data.flags & NFS_MOUNT_VER3) { + if (getfh3()) + return 0; + } else { + if (getfh2()) + return 0; + } + set_sockaddr((struct sockaddr_in *) &nfs_data.addr, servaddr, nfs_port); + return mount("/dev/root", "/mnt", "nfs", 0, &nfs_data) == 0; +} diff --git a/klibc/klibc/tests/setjmptest.c b/klibc/klibc/tests/setjmptest.c new file mode 100644 index 0000000000..a199eedab8 --- /dev/null +++ b/klibc/klibc/tests/setjmptest.c @@ -0,0 +1,36 @@ +/* + * setjmptest.c + */ + +#include <stdio.h> +#include <setjmp.h> + +static jmp_buf buf; + +void do_stuff(int v) +{ + printf("setjmp returned %d\n", v); + longjmp(buf, v+1); +} + +void recurse(int ctr, int v) +{ + if ( ctr-- ) { + recurse(ctr, v); + } else { + do_stuff(v); + } + _fwrite(".", 1, stdout); +} + +int main(void) +{ + int v; + + v = setjmp(buf); + + if ( v < 256 ) + recurse(v,v); + + return 0; +} diff --git a/klibc/klibc/tests/testrand48.c b/klibc/klibc/tests/testrand48.c new file mode 100644 index 0000000000..bf046b6bda --- /dev/null +++ b/klibc/klibc/tests/testrand48.c @@ -0,0 +1,19 @@ +#include <stdlib.h> +#include <stdio.h> + +int main(void) +{ + unsigned short seed1[] = { 0x1234, 0x5678, 0x9abc }; + unsigned short *oldseed; + + oldseed = seed48(seed1); + printf("Initial seed: %#06x %#06x %#06x\n", + oldseed[0], oldseed[1], oldseed[2]); + + printf("lrand48() = %ld\n", lrand48()); + + seed48(seed1); + printf("mrand48() = %ld\n", mrand48()); + + return 1; +} diff --git a/klibc/klibc/tests/testvsnp.c b/klibc/klibc/tests/testvsnp.c new file mode 100644 index 0000000000..c86e8b30fb --- /dev/null +++ b/klibc/klibc/tests/testvsnp.c @@ -0,0 +1,115 @@ +#include <assert.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdint.h> +#include <string.h> +#include <stdio.h> + +int main(void) +{ + int r, i; + char buffer[512]; + + r = snprintf(buffer, 512, "Hello, %d", 37); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 512, "Hello, %'d", 37373737); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 512, "Hello, %'x", 0xdeadbeef); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 512, "Hello, %'#X", 0xdeadbeef); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 512, "Hello, %'#llo", 0123456701234567ULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + /* Make sure overflow works correctly */ + memset(buffer, '\xff', 512); + r = snprintf(buffer, 16, "Hello, %'#llo", 0123456701234567ULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + for ( i = 16 ; i < 512 ; i++ ) + assert ( buffer[i] == '\xff' ); + + r = snprintf(buffer, 512, "Hello, %'#40.20llo", 0123456701234567ULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 512, "Hello, %'#-40.20llo", 0123456701234567ULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 512, "Hello, %'#*.*llo", 40, 20, 0123456701234567ULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 512, "Hello, %'#*.*llo", -40, 20, 0123456701234567ULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 512, "Hello, %'#*.*llo", -40, -20, 0123456701234567ULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 512, "Hello, %'#*.*llx", -40, -20, 0123456701234567ULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 512, "Hello, %p", &buffer); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 512, "Hello, %P", &buffer); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 512, "Hello, %20p", &buffer); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 512, "Hello, %-20p", &buffer); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 512, "Hello, %-20p", NULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 20, "Hello, %'-20p", NULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 15, "Hello, %'-20p", NULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 3, "Hello, %'-20p", NULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + /* This shouldn't change buffer in any way! */ + r = snprintf(buffer, 0, "Hello, %'-20p", NULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + for ( i = -30 ; i <= 30 ; i++ ) { + r = snprintf(buffer, 40, "Hello, %'*p", i, NULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + } + + r = snprintf(buffer, 40, "Hello, %'-20s", "String"); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 40, "Hello, %'20s", "String"); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 40, "Hello, %'020s", "String"); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 40, "Hello, %'-20s", NULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 40, "Hello, %'20s", NULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 40, "Hello, %'020s", NULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 40, "Hello, %'-20c", '*'); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 40, "Hello, %'20c", '*'); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 40, "Hello, %'020c", '*'); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + return 0; +} + diff --git a/klibc/klibc/time.c b/klibc/klibc/time.c new file mode 100644 index 0000000000..8f6e89738d --- /dev/null +++ b/klibc/klibc/time.c @@ -0,0 +1,27 @@ +/* + * time.c + */ + +#include <time.h> +#include <sys/time.h> +#include <sys/syscall.h> + +#ifdef __NR_time + +_syscall1(time_t,time,time_t *,t); + +#else + +time_t time(time_t *t) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + + if ( t ) + *t = (time_t)tv.tv_sec; + + return (time_t)tv.tv_sec; +} + +#endif diff --git a/klibc/klibc/umount.c b/klibc/klibc/umount.c new file mode 100644 index 0000000000..9a8e62a779 --- /dev/null +++ b/klibc/klibc/umount.c @@ -0,0 +1,12 @@ +/* + * umount.c + * + * Single-argument form of umount + */ + +#include <sys/mount.h> + +int umount(const char *dir) +{ + return umount2(dir, 0); +} diff --git a/klibc/klibc/unsetenv.c b/klibc/klibc/unsetenv.c new file mode 100644 index 0000000000..5f39f3d8f9 --- /dev/null +++ b/klibc/klibc/unsetenv.c @@ -0,0 +1,40 @@ +/* + * unsetenv.c + */ + +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +int unsetenv(const char *name) +{ + size_t len; + char **p, *q; + const char *z; + + if ( !name || !name[0] ) { + errno = EINVAL; + return -1; + } + + len = 0; + for ( z = name ; *z ; z++ ) { + len++; + if ( *z == '=' ) { + errno = EINVAL; + return -1; + } + } + + for ( p = environ ; (q = *p) ; p++ ) { + if ( !strncmp(name,q,len) && q[len] == '=' ) + break; + } + + for ( ; (q = *p) ; p++ ) { + p[0] = p[1]; + } + + return 0; +} diff --git a/klibc/klibc/usleep.c b/klibc/klibc/usleep.c new file mode 100644 index 0000000000..b63352eebf --- /dev/null +++ b/klibc/klibc/usleep.c @@ -0,0 +1,15 @@ +/* + * usleep.c + */ + +#include <errno.h> +#include <time.h> + +void usleep(unsigned long usec) +{ + struct timespec ts; + + ts.tv_sec = usec/1000000UL; + ts.tv_nsec = (usec%1000000UL) * 1000; + while ( nanosleep(&ts,&ts) == -1 && errno == EINTR ); +} diff --git a/klibc/klibc/utime.c b/klibc/klibc/utime.c new file mode 100644 index 0000000000..a00b589629 --- /dev/null +++ b/klibc/klibc/utime.c @@ -0,0 +1,30 @@ +/* + * utime.c + */ + +#include <utime.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/syscall.h> + +#ifdef __NR_utime + +_syscall2(int,utime,const char *,filename,const struct utimbuf *,buf); + +#else + +static inline _syscall2(int,utimes,const char *,filename, const struct timeval *,tvp); + +int utime(const char *filename, const struct utimbuf *buf) +{ + struct timeval tvp[2]; + + tvp[0].tv_sec = buf->actime; + tvp[0].tv_usec = 0; + tvp[1].tv_sec = buf->modtime; + tvp[1].tv_usec = 0; + + return utimes(filename, tvp); +} + +#endif diff --git a/klibc/klibc/vfprintf.c b/klibc/klibc/vfprintf.c new file mode 100644 index 0000000000..39cf9838f6 --- /dev/null +++ b/klibc/klibc/vfprintf.c @@ -0,0 +1,26 @@ +/* + * vfprintf.c + */ + +#include <stdio.h> +#include <string.h> +#include <stdarg.h> +#include <unistd.h> + +#define BUFFER_SIZE 32768 + +int vfprintf(FILE *file, const char *format, va_list ap) +{ + int rv; + char buffer[BUFFER_SIZE]; + + rv = vsnprintf(buffer, BUFFER_SIZE, format, ap); + + if ( rv < 0 ) + return rv; + + if ( rv > BUFFER_SIZE-1 ) + rv = BUFFER_SIZE-1; + + return _fwrite(buffer, rv, file); +} diff --git a/klibc/klibc/vprintf.c b/klibc/klibc/vprintf.c new file mode 100644 index 0000000000..7d6066586f --- /dev/null +++ b/klibc/klibc/vprintf.c @@ -0,0 +1,11 @@ +/* + * vprintf.c + */ + +#include <stdio.h> +#include <stdarg.h> + +int vprintf(const char *format, va_list ap) +{ + return vfprintf(stdout, format, ap); +} diff --git a/klibc/klibc/vsnprintf.c b/klibc/klibc/vsnprintf.c new file mode 100644 index 0000000000..5cb9331954 --- /dev/null +++ b/klibc/klibc/vsnprintf.c @@ -0,0 +1,433 @@ +/* + * vsnprintf.c + * + * vsnprintf(), from which the rest of the printf() + * family is built + */ + +#include <stdarg.h> +#include <stddef.h> +#include <inttypes.h> +#include <string.h> +#include <limits.h> +#include <stdio.h> + +enum flags { + FL_ZERO = 0x01, /* Zero modifier */ + FL_MINUS = 0x02, /* Minus modifier */ + FL_PLUS = 0x04, /* Plus modifier */ + FL_TICK = 0x08, /* ' modifier */ + FL_SPACE = 0x10, /* Space modifier */ + FL_HASH = 0x20, /* # modifier */ + FL_SIGNED = 0x40, /* Number is signed */ + FL_UPPER = 0x80 /* Upper case digits */ +}; + +/* These may have to be adjusted on certain implementations */ +enum ranks { + rank_char = -2, + rank_short = -1, + rank_int = 0, + rank_long = 1, + rank_longlong = 2 +}; + +#define MIN_RANK rank_char +#define MAX_RANK rank_longlong + +#define INTMAX_RANK rank_longlong +#define SIZE_T_RANK rank_long +#define PTRDIFF_T_RANK rank_long + +#define EMIT(x) ({ if (o<n){*q++ = (x);} o++; }) + +static size_t +format_int(char *q, size_t n, uintmax_t val, enum flags flags, + int base, int width, int prec) +{ + char *qq; + size_t o = 0, oo; + static const char lcdigits[] = "0123456789abcdef"; + static const char ucdigits[] = "0123456789ABCDEF"; + const char *digits; + uintmax_t tmpval; + int minus = 0; + int ndigits = 0, nchars; + int tickskip, b4tick; + + /* Select type of digits */ + digits = (flags & FL_UPPER) ? ucdigits : lcdigits; + + /* If signed, separate out the minus */ + if ( flags & FL_SIGNED && (intmax_t)val < 0 ) { + minus = 1; + val = (uintmax_t)(-(intmax_t)val); + } + + /* Count the number of digits needed. This returns zero for 0. */ + tmpval = val; + while ( tmpval ) { + tmpval /= base; + ndigits++; + } + + /* Adjust ndigits for size of output */ + + if ( flags & FL_HASH && base == 8 ) { + if ( prec < ndigits+1 ) + prec = ndigits+1; + } + + if ( ndigits < prec ) { + ndigits = prec; /* Mandatory number padding */ + } else if ( val == 0 ) { + ndigits = 1; /* Zero still requires space */ + } + + /* For ', figure out what the skip should be */ + if ( flags & FL_TICK ) { + tickskip = (base == 16) ? 4 : 3; + } else { + tickskip = ndigits; /* No tick marks */ + } + + /* Tick marks aren't digits, but generated by the number converter */ + ndigits += (ndigits-1)/tickskip; + + /* Now compute the number of nondigits */ + nchars = ndigits; + + if ( minus || (flags & (FL_PLUS|FL_SPACE)) ) + nchars++; /* Need space for sign */ + if ( (flags & FL_HASH) && base == 16 ) { + nchars += 2; /* Add 0x for hex */ + } + + /* Emit early space padding */ + if ( !(flags & (FL_MINUS|FL_ZERO)) && width > nchars ) { + while ( width > nchars ) { + EMIT(' '); + width--; + } + } + + /* Emit nondigits */ + if ( minus ) + EMIT('-'); + else if ( flags & FL_PLUS ) + EMIT('+'); + else if ( flags & FL_SPACE ) + EMIT(' '); + + if ( (flags & FL_HASH) && base == 16 ) { + EMIT('0'); + EMIT((flags & FL_UPPER) ? 'X' : 'x'); + } + + /* Emit zero padding */ + if ( (flags & (FL_MINUS|FL_ZERO)) == FL_ZERO && width > ndigits ) { + while ( width > nchars ) { + EMIT('0'); + width--; + } + } + + /* Generate the number. This is done from right to left. */ + q += ndigits; /* Advance the pointer to end of number */ + o += ndigits; + qq = q; oo = o; /* Temporary values */ + + b4tick = tickskip; + while ( ndigits > 0 ) { + if ( !b4tick-- ) { + qq--; oo--; ndigits--; + if ( oo < n ) *qq = '_'; + b4tick = tickskip-1; + } + qq--; oo--; ndigits--; + if ( oo < n ) *qq = digits[val%base]; + val /= base; + } + + /* Emit late space padding */ + while ( (flags & FL_MINUS) && width > nchars ) { + EMIT(' '); + width--; + } + + return o; +} + + +int vsnprintf(char *buffer, size_t n, const char *format, va_list ap) +{ + const char *p = format; + char ch; + char *q = buffer; + size_t o = 0; /* Number of characters output */ + uintmax_t val = 0; + int rank = rank_int; /* Default rank */ + int width = 0; + int prec = -1; + int base; + size_t sz; + enum flags flags = 0; + enum { + st_normal, /* Ground state */ + st_flags, /* Special flags */ + st_width, /* Field width */ + st_prec, /* Field precision */ + st_modifiers /* Length or conversion modifiers */ + } state = st_normal; + const char *sarg; /* %s string argument */ + char carg; /* %c char argument */ + int slen; /* String length */ + + while ( (ch = *p++) ) { + switch ( state ) { + case st_normal: + if ( ch == '%' ) { + state = st_flags; + flags = 0; rank = rank_int; width = 0; prec = -1; + } else { + EMIT(ch); + } + break; + + case st_flags: + switch ( ch ) { + case '-': + flags |= FL_MINUS; + break; + case '+': + flags |= FL_PLUS; + break; + case '\'': + flags |= FL_TICK; + break; + case ' ': + flags |= FL_SPACE; + break; + case '#': + flags |= FL_HASH; + break; + case '0': + flags |= FL_ZERO; + break; + default: + state = st_width; + p--; /* Process this character again */ + break; + } + break; + + case st_width: + if ( ch >= '0' && ch <= '9' ) { + width = width*10+(ch-'0'); + } else if ( ch == '*' ) { + width = va_arg(ap, int); + if ( width < 0 ) { + width = -width; + flags |= FL_MINUS; + } + } else if ( ch == '.' ) { + prec = 0; /* Precision given */ + state = st_prec; + } else { + state = st_modifiers; + p--; /* Process this character again */ + } + break; + + case st_prec: + if ( ch >= '0' && ch <= '9' ) { + prec = prec*10+(ch-'0'); + } else if ( ch == '*' ) { + prec = va_arg(ap, int); + if ( prec < 0 ) + prec = -1; + } else { + state = st_modifiers; + p--; /* Process this character again */ + } + break; + + case st_modifiers: + switch ( ch ) { + /* Length modifiers - nonterminal sequences */ + case 'h': + rank--; /* Shorter rank */ + break; + case 'l': + rank++; /* Longer rank */ + break; + case 'j': + rank = INTMAX_RANK; + break; + case 'z': + rank = SIZE_T_RANK; + break; + case 't': + rank = PTRDIFF_T_RANK; + break; + case 'L': + case 'q': + rank += 2; + break; + default: + /* Output modifiers - terminal sequences */ + state = st_normal; /* Next state will be normal */ + if ( rank < MIN_RANK ) /* Canonicalize rank */ + rank = MIN_RANK; + else if ( rank > MAX_RANK ) + rank = MAX_RANK; + + switch ( ch ) { + case 'P': /* Upper case pointer */ + flags |= FL_UPPER; + /* fall through */ + case 'p': /* Pointer */ + base = 16; + prec = (CHAR_BIT*sizeof(void *)+3)/4; + flags |= FL_HASH; + val = (uintmax_t)(uintptr_t)va_arg(ap, void *); + goto is_integer; + + case 'd': /* Signed decimal output */ + case 'i': + base = 10; + flags |= FL_SIGNED; + switch (rank) { + case rank_char: + /* Yes, all these casts are needed... */ + val = (uintmax_t)(intmax_t)(signed char)va_arg(ap, signed int); + break; + case rank_short: + val = (uintmax_t)(intmax_t)(signed short)va_arg(ap, signed int); + break; + case rank_int: + val = (uintmax_t)(intmax_t)va_arg(ap, signed int); + break; + case rank_long: + val = (uintmax_t)(intmax_t)va_arg(ap, signed long); + break; + case rank_longlong: + val = (uintmax_t)(intmax_t)va_arg(ap, signed long long); + break; + } + goto is_integer; + case 'o': /* Octal */ + base = 8; + goto is_unsigned; + case 'u': /* Unsigned decimal */ + base = 10; + goto is_unsigned; + case 'X': /* Upper case hexadecimal */ + flags |= FL_UPPER; + /* fall through */ + case 'x': /* Hexadecimal */ + base = 16; + goto is_unsigned; + + is_unsigned: + switch (rank) { + case rank_char: + val = (uintmax_t)(unsigned char)va_arg(ap, unsigned int); + break; + case rank_short: + val = (uintmax_t)(unsigned short)va_arg(ap, unsigned int); + break; + case rank_int: + val = (uintmax_t)va_arg(ap, unsigned int); + break; + case rank_long: + val = (uintmax_t)va_arg(ap, unsigned long); + break; + case rank_longlong: + val = (uintmax_t)va_arg(ap, unsigned long long); + break; + } + /* fall through */ + + is_integer: + sz = format_int(q, (o<n) ? n-o : 0, val, flags, base, width, prec); + q += sz; o += sz; + break; + + case 'c': /* Character */ + carg = (char)va_arg(ap, int); + sarg = &carg; + slen = 1; + goto is_string; + case 's': /* String */ + sarg = va_arg(ap, const char *); + sarg = sarg ? sarg : "(null)"; + slen = strlen(sarg); + goto is_string; + + is_string: + { + char sch; + int i; + + if ( prec != -1 && slen > prec ) + slen = prec; + + if ( width > slen && !(flags & FL_MINUS) ) { + char pad = (flags & FL_ZERO) ? '0' : ' '; + while ( width > slen ) { + EMIT(pad); + width--; + } + } + for ( i = slen ; i ; i-- ) { + sch = *sarg++; + EMIT(sch); + } + if ( width > slen && (flags & FL_MINUS) ) { + while ( width > slen ) { + EMIT(' '); + width--; + } + } + } + break; + + case 'n': /* Output the number of characters written */ + { + switch (rank) { + case rank_char: + *va_arg(ap, signed char *) = o; + break; + case rank_short: + *va_arg(ap, signed short *) = o; + break; + case rank_int: + *va_arg(ap, signed int *) = o; + break; + case rank_long: + *va_arg(ap, signed long *) = o; + break; + case rank_longlong: + *va_arg(ap, signed long long *) = o; + break; + } + } + break; + + default: /* Anything else, including % */ + EMIT(ch); + break; + } + } + } + } + + /* Null-terminate the string */ + if ( o<n ) + *q = '\0'; /* No overflow */ + else if ( n>0 ) + buffer[n-1] = '\0'; /* Overflow - terminate at end of buffer */ + + return o; +} diff --git a/klibc/klibc/vsprintf.c b/klibc/klibc/vsprintf.c new file mode 100644 index 0000000000..4a6100e70c --- /dev/null +++ b/klibc/klibc/vsprintf.c @@ -0,0 +1,11 @@ +/* + * vsprintf.c + */ + +#include <stdio.h> +#include <unistd.h> + +int vsprintf(char *buffer, const char *format, va_list ap) +{ + return vsnprintf(buffer, ~(size_t)0, format, ap); +} diff --git a/klibc/klibc/vsscanf.c b/klibc/klibc/vsscanf.c new file mode 100644 index 0000000000..12a82b2747 --- /dev/null +++ b/klibc/klibc/vsscanf.c @@ -0,0 +1,365 @@ +/* + * vsscanf.c + * + * vsscanf(), from which the rest of the scanf() + * family is built + */ + +#include <ctype.h> +#include <stdarg.h> +#include <stddef.h> +#include <inttypes.h> +#include <string.h> +#include <limits.h> +#include <stdio.h> + +#ifndef LONG_BIT +#define LONG_BIT (CHAR_BIT*sizeof(long)) +#endif + +enum flags { + FL_SPLAT = 0x01, /* Drop the value, do not assign */ + FL_INV = 0x02, /* Character-set with inverse */ + FL_WIDTH = 0x04, /* Field width specified */ + FL_MINUS = 0x08, /* Negative number */ +}; + +enum ranks { + rank_char = -2, + rank_short = -1, + rank_int = 0, + rank_long = 1, + rank_longlong = 2, + rank_ptr = INT_MAX /* Special value used for pointers */ +}; + +#define MIN_RANK rank_char +#define MAX_RANK rank_longlong + +#define INTMAX_RANK rank_longlong +#define SIZE_T_RANK rank_long +#define PTRDIFF_T_RANK rank_long + +enum bail { + bail_none = 0, /* No error condition */ + bail_eof, /* Hit EOF */ + bail_err /* Conversion mismatch */ +}; + +static inline const char * +skipspace(const char *p) +{ + while ( isspace((unsigned char)*p) ) p++; + return p; +} + +#undef set_bit +static inline void +set_bit(unsigned long *bitmap, unsigned int bit) +{ + bitmap[bit/LONG_BIT] |= 1UL << (bit%LONG_BIT); +} + +#undef test_bit +static inline int +test_bit(unsigned long *bitmap, unsigned int bit) +{ + return (int)(bitmap[bit/LONG_BIT] >> (bit%LONG_BIT)) & 1; +} + +int vsscanf(const char *buffer, const char *format, va_list ap) +{ + const char *p = format; + char ch; + const char *q = buffer; + const char *qq; + uintmax_t val = 0; + int rank = rank_int; /* Default rank */ + unsigned int width = UINT_MAX; + int base; + enum flags flags = 0; + enum { + st_normal, /* Ground state */ + st_flags, /* Special flags */ + st_width, /* Field width */ + st_modifiers, /* Length or conversion modifiers */ + st_match_init, /* Initial state of %[ sequence */ + st_match, /* Main state of %[ sequence */ + st_match_range, /* After - in a %[ sequence */ + } state = st_normal; + char *sarg = NULL; /* %s %c or %[ string argument */ + enum bail bail = bail_none; + int sign; + int converted = 0; /* Successful conversions */ + unsigned long matchmap[((1 << CHAR_BIT)+(LONG_BIT-1))/LONG_BIT]; + int matchinv = 0; /* Is match map inverted? */ + unsigned char range_start = 0; + + while ( (ch = *p++) && !bail ) { + switch ( state ) { + case st_normal: + if ( ch == '%' ) { + state = st_flags; + flags = 0; rank = rank_int; width = UINT_MAX; + } else if ( isspace((unsigned char)ch) ) { + q = skipspace(q); + } else { + if ( *q == ch ) + q++; + else + bail = bail_err; /* Match failure */ + } + break; + + case st_flags: + switch ( ch ) { + case '*': + flags |= FL_SPLAT; + break; + case '0' ... '9': + width = (ch-'0'); + state = st_width; + flags |= FL_WIDTH; + break; + default: + state = st_modifiers; + p--; /* Process this character again */ + break; + } + break; + + case st_width: + if ( ch >= '0' && ch <= '9' ) { + width = width*10+(ch-'0'); + } else { + state = st_modifiers; + p--; /* Process this character again */ + } + break; + + case st_modifiers: + switch ( ch ) { + /* Length modifiers - nonterminal sequences */ + case 'h': + rank--; /* Shorter rank */ + break; + case 'l': + rank++; /* Longer rank */ + break; + case 'j': + rank = INTMAX_RANK; + break; + case 'z': + rank = SIZE_T_RANK; + break; + case 't': + rank = PTRDIFF_T_RANK; + break; + case 'L': + case 'q': + rank = rank_longlong; /* long double/long long */ + break; + + default: + /* Output modifiers - terminal sequences */ + state = st_normal; /* Next state will be normal */ + if ( rank < MIN_RANK ) /* Canonicalize rank */ + rank = MIN_RANK; + else if ( rank > MAX_RANK ) + rank = MAX_RANK; + + switch ( ch ) { + case 'P': /* Upper case pointer */ + case 'p': /* Pointer */ +#if 0 /* Enable this to allow null pointers by name */ + q = skipspace(q); + if ( !isdigit((unsigned char)*q) ) { + static const char * const nullnames[] = + { "null", "nul", "nil", "(null)", "(nul)", "(nil)", 0 }; + const char * const *np; + + /* Check to see if it's a null pointer by name */ + for ( np = nullnames ; *np ; np++ ) { + if ( !strncasecmp(q, *np, strlen(*np)) ) { + val = (uintmax_t)((void *)NULL); + goto set_integer; + } + } + /* Failure */ + bail = bail_err; + break; + } + /* else */ +#endif + rank = rank_ptr; + base = 0; sign = 0; + goto scan_int; + + case 'i': /* Base-independent integer */ + base = 0; sign = 1; + goto scan_int; + + case 'd': /* Decimal integer */ + base = 10; sign = 1; + goto scan_int; + + case 'o': /* Octal integer */ + base = 8; sign = 0; + goto scan_int; + + case 'u': /* Unsigned decimal integer */ + base = 10; sign = 0; + goto scan_int; + + case 'x': /* Hexadecimal integer */ + case 'X': + base = 16; sign = 0; + goto scan_int; + + case 'n': /* Number of characters consumed */ + val = (q-buffer); + goto set_integer; + + scan_int: + q = skipspace(q); + if ( !*q ) { + bail = bail_eof; + break; + } + val = strntoumax(q, (char **)&qq, base, width); + if ( qq == q ) { + bail = bail_err; + break; + } + q = qq; + converted++; + /* fall through */ + + set_integer: + if ( !(flags & FL_SPLAT) ) { + switch(rank) { + case rank_char: + *va_arg(ap, unsigned char *) = (unsigned char)val; + break; + case rank_short: + *va_arg(ap, unsigned short *) = (unsigned short)val; + break; + case rank_int: + *va_arg(ap, unsigned int *) = (unsigned int)val; + break; + case rank_long: + *va_arg(ap, unsigned long *) = (unsigned long)val; + break; + case rank_longlong: + *va_arg(ap, unsigned long long *) = (unsigned long long)val; + break; + case rank_ptr: + *va_arg(ap, void **) = (void *)(uintptr_t)val; + break; + } + } + break; + + case 'c': /* Character */ + width = (flags & FL_WIDTH) ? width : 1; /* Default width == 1 */ + sarg = va_arg(ap, char *); + while ( width-- ) { + if ( !*q ) { + bail = bail_eof; + break; + } + *sarg++ = *q++; + } + if ( !bail ) + converted++; + break; + + case 's': /* String */ + { + char *sp; + sp = sarg = va_arg(ap, char *); + while ( width-- && *q && !isspace((unsigned char)*q) ) { + *sp++ = *q++; + } + if ( sarg != sp ) { + *sp = '\0'; /* Terminate output */ + converted++; + } else { + bail = bail_eof; + } + } + break; + + case '[': /* Character range */ + sarg = va_arg(ap, char *); + state = st_match_init; + matchinv = 0; + memset(matchmap, 0, sizeof matchmap); + break; + + case '%': /* %% sequence */ + if ( *q == '%' ) + q++; + else + bail = bail_err; + break; + + default: /* Anything else */ + bail = bail_err; /* Unknown sequence */ + break; + } + } + break; + + case st_match_init: /* Initial state for %[ match */ + if ( ch == '^' && !(flags & FL_INV) ) { + matchinv = 1; + } else { + set_bit(matchmap, (unsigned char)ch); + state = st_match; + } + break; + + case st_match: /* Main state for %[ match */ + if ( ch == ']' ) { + goto match_run; + } else if ( ch == '-' ) { + range_start = (unsigned char)ch; + state = st_match_range; + } else { + set_bit(matchmap, (unsigned char)ch); + } + break; + + case st_match_range: /* %[ match after - */ + if ( ch == ']' ) { + set_bit(matchmap, (unsigned char)'-'); /* - was last character */ + goto match_run; + } else { + int i; + for ( i = range_start ; i < (unsigned char)ch ; i++ ) + set_bit(matchmap, i); + state = st_match; + } + break; + + match_run: /* Match expression finished */ + qq = q; + while ( width && *q && test_bit(matchmap, (unsigned char)*q)^matchinv ) { + *sarg++ = *q++; + } + if ( q != qq ) { + *sarg = '\0'; + converted++; + } else { + bail = *q ? bail_err : bail_eof; + } + break; + } + } + + if ( bail == bail_eof && !converted ) + converted = -1; /* Return EOF (-1) */ + + return converted; +} diff --git a/klibc/klibc/wait.c b/klibc/klibc/wait.c new file mode 100644 index 0000000000..5e0bbe29c5 --- /dev/null +++ b/klibc/klibc/wait.c @@ -0,0 +1,12 @@ +/* + * wait.c + */ + +#include <stdlib.h> +#include <sys/wait.h> +#include <sys/types.h> + +pid_t wait(int *status) +{ + return wait4((pid_t)-1, status, 0, NULL); +} diff --git a/klibc/klibc/wait3.c b/klibc/klibc/wait3.c new file mode 100644 index 0000000000..48840ad155 --- /dev/null +++ b/klibc/klibc/wait3.c @@ -0,0 +1,12 @@ +/* + * wait3.c + */ + +#include <sys/types.h> +#include <sys/resource.h> +#include <sys/wait.h> + +pid_t wait3(int *status, int options, struct rusage *rusage) +{ + return wait4((pid_t)-1, status, options, rusage); +} diff --git a/klibc/klibc/waitpid.c b/klibc/klibc/waitpid.c new file mode 100644 index 0000000000..f7c5cbfbc0 --- /dev/null +++ b/klibc/klibc/waitpid.c @@ -0,0 +1,12 @@ +/* + * waitpid.c + */ + +#include <sys/types.h> +#include <sys/resource.h> +#include <sys/wait.h> + +pid_t waitpid(pid_t pid, int *status, int options) +{ + return wait4(pid, status, options, NULL); +} |