diff options
23 files changed, 732 insertions, 154 deletions
diff --git a/klibc/klibc/CAVEATS b/klibc/klibc/CAVEATS index c7131ac367..5bc11e4179 100644 --- a/klibc/klibc/CAVEATS +++ b/klibc/klibc/CAVEATS @@ -49,3 +49,13 @@ theading: klibc is not thread-safe. Consequently, clone() or any of the pthreads functions are not included. + +bsd_signal vs sysv_signal: +-------------------------- + +There is no signal() call, because you never know if you want +Linux/SysV semantics (SA_RESETHAND) or GNU/BSD semantics (SA_RESTART). +The best, in *any* circumstances, is to never use signal() and instead +use sigaction(), but in order to simplify porting you can use either +sysv_signal() or bsd_signal(), depending on what you actually want. + diff --git a/klibc/klibc/MCONFIG b/klibc/klibc/MCONFIG index a46a98a9dd..253a9461b7 100644 --- a/klibc/klibc/MCONFIG +++ b/klibc/klibc/MCONFIG @@ -5,45 +5,9 @@ SRCROOT = .. include ../MCONFIG +include ../MRULES 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 index def201524a..0d5b197f0d 100644 --- a/klibc/klibc/Makefile +++ b/klibc/klibc/Makefile @@ -22,7 +22,7 @@ LIBOBJS = vsnprintf.o snprintf.o vsprintf.o sprintf.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 \ + __signal.o sysv_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 getpagesize.o \ memcpy.o memcmp.o memset.o memccpy.o memmem.o memswap.o \ @@ -33,7 +33,8 @@ LIBOBJS = vsnprintf.o snprintf.o vsprintf.o sprintf.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 \ + getenv.o setenv.o putenv.o __put_env.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 \ diff --git a/klibc/klibc/README b/klibc/klibc/README index ce0ad7ba6a..4495908a22 100644 --- a/klibc/klibc/README +++ b/klibc/klibc/README @@ -9,12 +9,12 @@ 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.) + reasonably recent Linux kernel tree (2.4 or 2.6 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". + question, followed by a "make dep" (2.4) or "make prepare" (2.6). b) If you're cross-compiling, change ARCH in the main MCONFIG file to the appropriate architecture, and set CROSS to your toolchain @@ -34,16 +34,17 @@ b) If you're cross-compiling, change ARCH in the main MCONFIG file to The following is the last known status of various architectures: - Known to work: alpha arm ia64 i386 s390 s390x sparc + Known to work: alpha arm ia64 i386 ppc s390 s390x sparc sparc64 x86_64* Works static, not shared: mips* arm-thumb sh* - Might work: ppc ppc64 + Might work: ppc64 Need porting work: cris 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. + Shared library support requires binutils 2.13.90.0.4 or later on + many architectures. Note that even the "known to work" ones likely have bugs. Please report them if you run into them. @@ -52,6 +53,10 @@ 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. +Contact the klibc mailing list: + + http://www.zytor.com/mailman/listinfo/klibc + +... for more info. -hpa diff --git a/klibc/klibc/__put_env.c b/klibc/klibc/__put_env.c new file mode 100644 index 0000000000..7e55f2c43b --- /dev/null +++ b/klibc/klibc/__put_env.c @@ -0,0 +1,60 @@ +/* + * __put_env.c - common code for putenv() and setenv() + */ + +#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 */ +int __put_env(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; /* Possible 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] = str; /* Old NULL position */ + newenv[n] = NULL; + environ = newenv; + } + return 0; +} diff --git a/klibc/klibc/arch/x86_64/include/klibc/archsys.h b/klibc/klibc/arch/x86_64/include/klibc/archsys.h index 3bd8b0a5d9..2ec72cd397 100644 --- a/klibc/klibc/arch/x86_64/include/klibc/archsys.h +++ b/klibc/klibc/arch/x86_64/include/klibc/archsys.h @@ -7,9 +7,88 @@ #ifndef _KLIBC_ARCHSYS_H #define _KLIBC_ARCHSYS_H -/* x86-64 seems to miss _syscall6() from its headers */ +/* The x86-64 syscall headers are needlessly inefficient */ -#ifndef _syscall6 +#undef _syscall0 +#undef _syscall1 +#undef _syscall2 +#undef _syscall3 +#undef _syscall4 +#undef _syscall5 +#undef _syscall6 + +#define _syscall0(type,name) \ +type name (void) \ +{ \ +long __res; \ +__asm__ volatile (__syscall \ + : "=a" (__res) \ + : "0" (__NR_##name) \ + : __syscall_clobber); \ +__syscall_return(type,__res); \ +} + +#define _syscall1(type,name,type1,arg1) \ +type name (type1 arg1) \ +{ \ +long __res; \ +__asm__ volatile (__syscall \ + : "=a" (__res) \ + : "0" (__NR_##name),"D" (arg1) \ + : __syscall_clobber); \ +__syscall_return(type,__res); \ +} + +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name (type1 arg1,type2 arg2) \ +{ \ +long __res; \ +__asm__ volatile (__syscall \ + : "=a" (__res) \ + : "0" (__NR_##name),"D" (arg1),"S" (arg2) \ + : __syscall_clobber); \ +__syscall_return(type,__res); \ +} + +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name (type1 arg1,type2 arg2,type3 arg3) \ +{ \ +long __res; \ +__asm__ volatile (__syscall \ + : "=a" (__res) \ + : "0" (__NR_##name),"D" (arg1),"S" (arg2), \ + "d" (arg3) \ + : __syscall_clobber); \ +__syscall_return(type,__res); \ +} + +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \ +{ \ +long __res; \ +register type4 __r10 asm("%r10") = arg4; \ +__asm__ volatile (__syscall \ + : "=a" (__res) \ + : "0" (__NR_##name),"D" (arg1),"S" (arg2), \ + "d" (arg3),"r" (__r10) \ + : __syscall_clobber); \ +__syscall_return(type,__res); \ +} + +#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; \ +register type4 __r10 asm("%r10") = arg4; \ +register type5 __r8 asm("%r8") = arg5; \ +__asm__ volatile (__syscall \ + : "=a" (__res) \ + : "0" (__NR_##name),"D" (arg1),"S" (arg2), \ + "d" (arg3),"r" (__r10),"r" (__r8) \ + : __syscall_clobber); \ +__syscall_return(type,__res); \ +} #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ type5,arg5,type6,arg6) \ @@ -27,6 +106,4 @@ __asm__ volatile (__syscall \ __syscall_return(type,__res); \ } -#endif /* _syscall6 missing */ - #endif /* _KLIBC_ARCHSYS_H */ diff --git a/klibc/klibc/include/elf.h b/klibc/klibc/include/elf.h index bd0f3e7f9b..52f47d042e 100644 --- a/klibc/klibc/include/elf.h +++ b/klibc/klibc/include/elf.h @@ -5,8 +5,8 @@ #ifndef _ELF_H #define _ELF_H -#include <sys/types.h> -#include <linux/elf.h> +#include <sys/elf32.h> +#include <sys/elf64.h> #endif /* _ELF_H */ diff --git a/klibc/klibc/include/signal.h b/klibc/klibc/include/signal.h index f9eebb2a29..513b4e5a04 100644 --- a/klibc/klibc/include/signal.h +++ b/klibc/klibc/include/signal.h @@ -64,7 +64,7 @@ static __inline__ int sigismember(sigset_t *__set, int __signum) } __extern __sighandler_t __signal(int, __sighandler_t, int); -__extern __sighandler_t signal(int, __sighandler_t); +__extern __sighandler_t sysv_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 *); diff --git a/klibc/klibc/include/stdint.h b/klibc/klibc/include/stdint.h index 2022a30fd7..47fec18594 100644 --- a/klibc/klibc/include/stdint.h +++ b/klibc/klibc/include/stdint.h @@ -110,4 +110,7 @@ typedef uint64_t uintmax_t; #endif +/* Keep the kernel from trying to define these types... */ +#define __BIT_TYPES_DEFINED__ + #endif /* _STDINT_H */ diff --git a/klibc/klibc/include/sys/elf32.h b/klibc/klibc/include/sys/elf32.h new file mode 100644 index 0000000000..652de5bc5f --- /dev/null +++ b/klibc/klibc/include/sys/elf32.h @@ -0,0 +1,115 @@ +/* + * sys/elf32.h + */ + +#ifndef _SYS_ELF32_H +#define _SYS_ELF32_H + +#include <sys/elfcommon.h> + +/* ELF standard typedefs (yet more proof that <stdint.h> was way overdue) */ +typedef uint16_t Elf32_Half; +typedef int16_t Elf32_SHalf; +typedef uint32_t Elf32_Word; +typedef int32_t Elf32_Sword; +typedef uint64_t Elf32_Xword; +typedef int64_t Elf32_Sxword; + +typedef uint32_t Elf32_Off; +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Section; + +/* Dynamic header */ + +typedef struct elf32_dyn { + Elf32_Sword d_tag; + union{ + Elf32_Sword d_val; + Elf32_Addr d_ptr; + } d_un; +} Elf32_Dyn; + +/* Relocations */ + +#define ELF32_R_SYM(x) ((x) >> 8) +#define ELF32_R_TYPE(x) ((x) & 0xff) + +typedef struct elf32_rel { + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + +typedef struct elf32_rela { + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} Elf32_Rela; + +/* Symbol */ + +typedef struct elf32_sym { + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; +} Elf32_Sym; + +/* Main file header */ + +typedef struct elf32_hdr { + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} Elf32_Ehdr; + +/* Program header */ + +typedef struct elf32_phdr { + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr; + + +/* Section header */ + +typedef struct elf32_shdr { + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; + +/* Note header */ +typedef struct elf32_note { + Elf32_Word n_namesz; /* Name size */ + Elf32_Word n_descsz; /* Content size */ + Elf32_Word n_type; /* Content type */ +} Elf32_Nhdr; + +#endif /* _SYS_ELF32_H */ + diff --git a/klibc/klibc/include/sys/elf64.h b/klibc/klibc/include/sys/elf64.h new file mode 100644 index 0000000000..750ddac4d9 --- /dev/null +++ b/klibc/klibc/include/sys/elf64.h @@ -0,0 +1,115 @@ +/* + * sys/elf64.h + */ + +#ifndef _SYS_ELF64_H +#define _SYS_ELF64_H + +#include <sys/elfcommon.h> + +/* ELF standard typedefs (yet more proof that <stdint.h> was way overdue) */ +typedef uint16_t Elf64_Half; +typedef int16_t Elf64_SHalf; +typedef uint32_t Elf64_Word; +typedef int32_t Elf64_Sword; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + +typedef uint64_t Elf64_Off; +typedef uint64_t Elf64_Addr; +typedef uint16_t Elf64_Section; + +/* Dynamic header */ + +typedef struct elf64_dyn { + Elf64_Sxword d_tag; + union{ + Elf64_Xword d_val; + Elf64_Addr d_ptr; + } d_un; +} Elf64_Dyn; + +/* Relocations */ + +#define ELF64_R_SYM(x) ((x) >> 32) +#define ELF64_R_TYPE(x) ((x) & 0xffffffff) + +typedef struct elf64_rel { + Elf64_Addr r_offset; + Elf64_Xword r_info; +} Elf64_Rel; + +typedef struct elf64_rela { + Elf64_Addr r_offset; + Elf64_Xword r_info; + Elf64_Sxword r_addend; +} Elf64_Rela; + +/* Symbol */ + +typedef struct elf64_sym { + Elf64_Word st_name; + unsigned char st_info; + unsigned char st_other; + Elf64_Half st_shndx; + Elf64_Addr st_value; + Elf64_Xword st_size; +} Elf64_Sym; + +/* Main file header */ + +typedef struct elf64_hdr { + unsigned char e_ident[EI_NIDENT]; + Elf64_Half e_type; + Elf64_Half e_machine; + Elf64_Word e_version; + Elf64_Addr e_entry; + Elf64_Off e_phoff; + Elf64_Off e_shoff; + Elf64_Word e_flags; + Elf64_Half e_ehsize; + Elf64_Half e_phentsize; + Elf64_Half e_phnum; + Elf64_Half e_shentsize; + Elf64_Half e_shnum; + Elf64_Half e_shstrndx; +} Elf64_Ehdr; + +/* Program header */ + +typedef struct elf64_phdr { + Elf64_Word p_type; + Elf64_Word p_flags; + Elf64_Off p_offset; + Elf64_Addr p_vaddr; + Elf64_Addr p_paddr; + Elf64_Xword p_filesz; + Elf64_Xword p_memsz; + Elf64_Xword p_align; +} Elf64_Phdr; + + +/* Section header */ + +typedef struct elf64_shdr { + Elf64_Word sh_name; + Elf64_Word sh_type; + Elf64_Xword sh_flags; + Elf64_Addr sh_addr; + Elf64_Off sh_offset; + Elf64_Xword sh_size; + Elf64_Word sh_link; + Elf64_Word sh_info; + Elf64_Xword sh_addralign; + Elf64_Xword sh_entsize; +} Elf64_Shdr; + +/* Note header */ +typedef struct elf64_note { + Elf64_Word n_namesz; /* Name size */ + Elf64_Word n_descsz; /* Content size */ + Elf64_Word n_type; /* Content type */ +} Elf64_Nhdr; + +#endif /* _SYS_ELF64_H */ + diff --git a/klibc/klibc/include/sys/elfcommon.h b/klibc/klibc/include/sys/elfcommon.h new file mode 100644 index 0000000000..f984f6a56b --- /dev/null +++ b/klibc/klibc/include/sys/elfcommon.h @@ -0,0 +1,186 @@ +/* + * sys/elfcommon.h + */ + +#ifndef _SYS_ELFCOMMON_H +#define _SYS_ELFCOMMON_H + +/* Segment types */ +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_LOOS 0x60000000 +#define PT_HIOS 0x6fffffff +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff +#define PT_GNU_EH_FRAME 0x6474e550 /* Extension, eh? */ + +/* ELF file types */ +#define ET_NONE 0 +#define ET_REL 1 +#define ET_EXEC 2 +#define ET_DYN 3 +#define ET_CORE 4 +#define ET_LOPROC 0xff00 +#define ET_HIPROC 0xffff + +/* ELF machine types */ +#define EM_NONE 0 +#define EM_M32 1 +#define EM_SPARC 2 +#define EM_386 3 +#define EM_68K 4 +#define EM_88K 5 +#define EM_486 6 /* Not used in Linux at least */ +#define EM_860 7 +#define EM_MIPS 8 /* R3k, bigendian(?) */ +#define EM_MIPS_RS4_BE 10 /* R4k BE */ +#define EM_PARISC 15 +#define EM_SPARC32PLUS 18 +#define EM_PPC 20 +#define EM_PPC64 21 +#define EM_S390 22 +#define EM_SH 42 +#define EM_SPARCV9 43 /* v9 = SPARC64 */ +#define EM_H8_300H 47 +#define EM_H8S 48 +#define EM_IA_64 50 /* Itanic */ +#define EM_X86_64 62 +#define EM_CRIS 76 +#define EM_V850 87 +#define EM_ALPHA 0x9026 /* Interrim Alpha that stuck around */ +#define EM_CYGNUS_V850 0x9080 /* Old v850 ID used by Cygnus */ +#define EM_S390_OLD 0xA390 /* Obsolete interrim value for S/390 */ + +/* Dynamic type values */ +#define DT_NULL 0 +#define DT_NEEDED 1 +#define DT_PLTRELSZ 2 +#define DT_PLTGOT 3 +#define DT_HASH 4 +#define DT_STRTAB 5 +#define DT_SYMTAB 6 +#define DT_RELA 7 +#define DT_RELASZ 8 +#define DT_RELAENT 9 +#define DT_STRSZ 10 +#define DT_SYMENT 11 +#define DT_INIT 12 +#define DT_FINI 13 +#define DT_SONAME 14 +#define DT_RPATH 15 +#define DT_SYMBOLIC 16 +#define DT_REL 17 +#define DT_RELSZ 18 +#define DT_RELENT 19 +#define DT_PLTREL 20 +#define DT_DEBUG 21 +#define DT_TEXTREL 22 +#define DT_JMPREL 23 +#define DT_LOPROC 0x70000000 +#define DT_HIPROC 0x7fffffff + +/* Auxilliary table entries */ +#define AT_NULL 0 /* end of vector */ +#define AT_IGNORE 1 /* entry should be ignored */ +#define AT_EXECFD 2 /* file descriptor of program */ +#define AT_PHDR 3 /* program headers for program */ +#define AT_PHENT 4 /* size of program header entry */ +#define AT_PHNUM 5 /* number of program headers */ +#define AT_PAGESZ 6 /* system page size */ +#define AT_BASE 7 /* base address of interpreter */ +#define AT_FLAGS 8 /* flags */ +#define AT_ENTRY 9 /* entry point of program */ +#define AT_NOTELF 10 /* program is not ELF */ +#define AT_UID 11 /* real uid */ +#define AT_EUID 12 /* effective uid */ +#define AT_GID 13 /* real gid */ +#define AT_EGID 14 /* effective gid */ +#define AT_PLATFORM 15 /* string identifying CPU for optimizations */ +#define AT_HWCAP 16 /* arch dependent hints at CPU capabilities */ +#define AT_CLKTCK 17 /* frequency at which times() increments */ +/* 18..22 = ? */ +#define AT_SECURE 23 /* secure mode boolean */ + +/* Program header permission flags */ +#define PF_X 0x1 +#define PF_W 0x2 +#define PF_R 0x4 + +/* Section header types */ +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_NUM 12 +#define SHT_LOPROC 0x70000000 +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0xffffffff + +/* Section header flags */ +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 +#define SHF_MASKPROC 0xf0000000 + +/* Special section numbers */ +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_LOPROC 0xff00 +#define SHN_HIPROC 0xff1f +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 +#define SHN_HIRESERVE 0xffff + +/* Lenght of magic at the start of a file */ +#define EI_NIDENT 16 + +/* Magic number constants... */ +#define EI_MAG0 0 /* e_ident[] indexes */ +#define EI_MAG1 1 +#define EI_MAG2 2 +#define EI_MAG3 3 +#define EI_CLASS 4 +#define EI_DATA 5 +#define EI_VERSION 6 +#define EI_OSABI 7 +#define EI_PAD 8 + +#define ELFMAG0 0x7f /* EI_MAG */ +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +#define ELFCLASSNONE 0 /* EI_CLASS */ +#define ELFCLASS32 1 +#define ELFCLASS64 2 +#define ELFCLASSNUM 3 + +#define ELFDATANONE 0 /* e_ident[EI_DATA] */ +#define ELFDATA2LSB 1 +#define ELFDATA2MSB 2 + +#define EV_NONE 0 /* e_version, EI_VERSION */ +#define EV_CURRENT 1 +#define EV_NUM 2 + +#define ELFOSABI_NONE 0 +#define ELFOSABI_LINUX 3 + +#endif /* _SYS_ELFCOMMON_H */ + diff --git a/klibc/klibc/include/sys/sysmacros.h b/klibc/klibc/include/sys/sysmacros.h new file mode 100644 index 0000000000..7f1e0822b3 --- /dev/null +++ b/klibc/klibc/include/sys/sysmacros.h @@ -0,0 +1,31 @@ +/* + * sys/sysmacros.h + * + * Constructs to create and pick apart dev_t. This applies to the Linux 2.6 + * 32-bit dev_t format. + */ + +#ifndef _SYS_SYSMACROS_H +#define _SYS_SYSMACROS_H + +#ifndef _SYS_TYPES_H +# include <sys/types.h> +#endif + +static __inline__ int major(dev_t __d) +{ + return (__d >> 8) & 0xfff; +} + +static __inline__ int minor(dev_t __d) +{ + return (__d & 0xff) | ((__d >> 12) & 0xfff00); +} + +static __inline__ dev_t makedev(int __ma, int __mi) +{ + return ((__ma & 0xfff) << 8) | (__mi & 0xff) | ((__mi & 0xfff00) << 12); +} + +#endif /* _SYS_SYSMACROS_H */ + diff --git a/klibc/klibc/include/sys/time.h b/klibc/klibc/include/sys/time.h index 4eccf824a4..b503d21076 100644 --- a/klibc/klibc/include/sys/time.h +++ b/klibc/klibc/include/sys/time.h @@ -6,6 +6,7 @@ #define _SYS_TIME_H #include <klibc/extern.h> +#include <sys/types.h> #include <linux/time.h> __extern int gettimeofday(struct timeval *, struct timezone *); diff --git a/klibc/klibc/include/sys/types.h b/klibc/klibc/include/sys/types.h index a25873cc4b..0aaeeb1612 100644 --- a/klibc/klibc/include/sys/types.h +++ b/klibc/klibc/include/sys/types.h @@ -1,8 +1,5 @@ /* * 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 @@ -25,7 +22,7 @@ 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_off_t off_t; /* Should become __kernel_loff_t... */ typedef __kernel_pid_t pid_t; typedef __kernel_daddr_t daddr_t; typedef __kernel_key_t key_t; @@ -83,15 +80,11 @@ 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__) */ +/* Linux-specific? */ +typedef uint8_t u_int8_t; +typedef uint16_t u_int16_t; +typedef uint32_t u_int32_t; +typedef uint64_t u_int64_t; /* * transition to 64-bit sector_t, possibly making it an option... @@ -124,4 +117,9 @@ struct ustat { char f_fpack[6]; }; +/* + * Some apps want this in <sys/types.h> + */ +#include <sys/sysmacros.h> + #endif diff --git a/klibc/klibc/include/sys/wait.h b/klibc/klibc/include/sys/wait.h index cad6989bf7..4cfafc9408 100644 --- a/klibc/klibc/include/sys/wait.h +++ b/klibc/klibc/include/sys/wait.h @@ -11,6 +11,15 @@ #include <linux/wait.h> +#define WEXITSTATUS(s) (((s) & 0xff00) >> 8) +#define WTERMSIG(s) ((s) & 0x7f) +#define WIFEXITED(s) (WTERMSIG(s) == 0) +#define WIFSTOPPED(s) (WTERMSIG(s) == 0x7f) +/* Ugly hack to avoid multiple evaluation of "s" */ +#define WIFSIGNALED(s) (WTERMSIG((s)+1) >= 2) +#define WCOREDUMP(s) ((s) & 0x80) +#define WSTOPSIG(s) WEXITSTATUS(s) + __extern pid_t wait(int *); __extern pid_t waitpid(pid_t, int *, int); __extern pid_t wait3(int *, int, struct rusage *); diff --git a/klibc/klibc/include/unistd.h b/klibc/klibc/include/unistd.h index 3d5c6881d3..f1cde2376e 100644 --- a/klibc/klibc/include/unistd.h +++ b/klibc/klibc/include/unistd.h @@ -49,6 +49,12 @@ __extern int setresgid(gid_t, gid_t, gid_t); __extern int getfsuid(uid_t); __extern int setfsuid(uid_t); +/* Macros for access() */ +#define R_OK 4 /* Read */ +#define W_OK 2 /* Write */ +#define X_OK 1 /* Execute */ +#define F_OK 0 /* Existence */ + __extern int access(const char *, int); __extern int link(const char *, const char *); __extern int unlink(const char *); diff --git a/klibc/klibc/putenv.c b/klibc/klibc/putenv.c new file mode 100644 index 0000000000..8138c653b4 --- /dev/null +++ b/klibc/klibc/putenv.c @@ -0,0 +1,40 @@ +/* + * putenv.c + */ + +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +/* str should be a duplicated version of the input string; + len is the length of the key including the = sign */ +int __put_env(char *str, size_t len, int overwrite); + +int putenv(const char *str) +{ + char *s; + const char *e, *z; + + if ( !str ) { + errno = EINVAL; + return -1; + } + + e = NULL; + for ( z = str ; *z ; z++ ) { + if ( *z == '=' ) + e = z; + } + + if ( !e ) { + errno = EINVAL; + return -1; + } + + s = strdup(str); + if ( !s ) + return -1; + + return __put_env(s, e-str, 1); +} diff --git a/klibc/klibc/setenv.c b/klibc/klibc/setenv.c index d1118ff3ed..d4ada53d74 100644 --- a/klibc/klibc/setenv.c +++ b/klibc/klibc/setenv.c @@ -7,87 +7,9 @@ #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 __put_env(char *str, size_t len, int overwrite); int setenv(const char *name, const char *val, int overwrite) { @@ -117,8 +39,7 @@ int setenv(const char *name, const char *val, int overwrite) memcpy(s, name, l1); s[l1] = '='; - memcpy(s+l1+1, val, l2); - s[l1+l2+1] = '\0'; + memcpy(s+l1+1, val, l2+1); - return _putenv(s, l1+1, overwrite); + return __put_env(s, l1+1, overwrite); } diff --git a/klibc/klibc/signal.c b/klibc/klibc/sysv_signal.c index 982d0c659d..3e55a02bb5 100644 --- a/klibc/klibc/signal.c +++ b/klibc/klibc/sysv_signal.c @@ -1,10 +1,10 @@ /* - * signal.c + * sysv_signal.c */ #include <signal.h> -__sighandler_t signal(int signum, __sighandler_t handler) +__sighandler_t sysv_signal(int signum, __sighandler_t handler) { /* Linux/SysV signal() semantics */ return __signal(signum, handler, SA_RESETHAND); diff --git a/klibc/klibc/tests/getenvtest.c b/klibc/klibc/tests/environ.c index 07cac0cef7..6eeeb9197e 100644 --- a/klibc/klibc/tests/getenvtest.c +++ b/klibc/klibc/tests/environ.c @@ -17,10 +17,8 @@ int main(int argc, char *argv[], char *envp[]) } /* 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")); + for ( i = 0 ; envp[i] ; i++ ) + printf("%s\n", envp[i]); return 0; } diff --git a/klibc/klibc/tests/nfs_no_rpc.c b/klibc/klibc/tests/nfs_no_rpc.c index 11b9f61fea..5c17706b63 100644 --- a/klibc/klibc/tests/nfs_no_rpc.c +++ b/klibc/klibc/tests/nfs_no_rpc.c @@ -282,7 +282,7 @@ static int do_call(struct sockaddr_in *sin, u_int32_t msg[], u_int32_t rmsg[], int n; int fd; - signal(SIGALRM, timeout); + sysv_signal(SIGALRM, timeout); fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (fd < 0) goto Esocket; diff --git a/klibc/klibc/tests/setenvtest.c b/klibc/klibc/tests/setenvtest.c new file mode 100644 index 0000000000..111bef9dfe --- /dev/null +++ b/klibc/klibc/tests/setenvtest.c @@ -0,0 +1,38 @@ +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> + +int main(int argc, char *argv[]) +{ + (void)argc; (void)argv; + + /* Set SETENV */ + setenv("SETENV", "setenv", 1); + + /* Set PUTENV */ + putenv("PUTENV=putenv"); + + /* Print the results... */ + printf("SETENV = %s\n", getenv("SETENV")); + printf("PUTENV = %s\n", getenv("PUTENV")); + + /* Override tests */ + setenv("SETENV", "setenv_good", 1); + putenv("PUTENV=putenv_good"); + printf("SETENV = %s\n", getenv("SETENV")); + printf("PUTENV = %s\n", getenv("PUTENV")); + + /* Non-override test */ + setenv("SETENV", "setenv_bad", 0); + setenv("NEWENV", "newenv_good", 0); + printf("SETENV = %s\n", getenv("SETENV")); + printf("NEWENV = %s\n", getenv("NEWENV")); + + /* Undef test */ + unsetenv("SETENV"); + unsetenv("NEWENV"); + printf("SETENV = %s\n", getenv("SETENV")); + printf("NEWENV = %s\n", getenv("NEWENV")); + + return 0; +} |