diff -ruN sos/code/sos-code-article9.5/README.uclibc sos-code-article9.5/README.uclibc --- sos/code/sos-code-article9.5/README.uclibc 1970-01-01 01:00:00.000000000 +0100 +++ sos-code-article9.5/README.uclibc 2006-02-26 20:19:33.000000000 +0100 @@ -0,0 +1,181 @@ +uClibc and SOS +============== + +What is uClibc ? +---------------- + +uClibc (aka µClibc/pronounced yew-see-lib-see) is a C library for +developing embedded Linux systems. It is much smaller than the GNU C +Library, but nearly all applications supported by glibc also work +perfectly with uClibc. + +URL: http://www.uclibc.org + +Compiling uClibc and SOS, testing it ! +-------------------------------------- + +A very experimental port of uClibc for the SOS operating system has +been started by Thomas Petazzoni, . + +Here are the steps to compile it: + + 1) Fetch the SOS uClibc sources + + $ svn co https://ssl.bulix.org/svn/thomas/uclibc-sos/trunk/ uclibc-sos + + 2) Fetch the SOS kernel headers, adapted for uClibc + + $ svn co https://ssl.bulix.org/svn/thomas/uclibc-sos-headers/trunk/ uclibc-sos-headers + + 3) Configure and compile the uClibc + + a) Method 1: Using the provided configuration + + $ cd uclibc-sos + $ cp libc/sysdeps/sos/config.sos .config + $ make oldconfig + $ make headers + $ cd libc ; make + $ cd ../../ + + b) Method 2: Configuring yourself + + $ cd uclibc-sos + $ make menuconfig + + - Target System + -> Change to "SOS" + - Target System Features and Options + -> SOS kernel header location + -> Change to the location of uclibc-sos-headers. + - General Library Settings + -> Remove "Support global constructors and destructors" + -> Remove "POSIX Threading support" + -> Remove "Large File Support" + -> Remove "Support only Unix 98 PTYs" + - uClibc development/debugging options + -> Build uClibc with debugging symbols + - Save and exit. + + $ make headers + $ cd libc ; make + $ cd ../../ + + (If you're cross-compiling, you're going to use 'make + CROSS=i586-pc-elf' instead of simply 'make') + + 4) Fetch the latest version of SOS and patch it + + (The version tested is 9.5. Patches apply to this version only.) + + a) Fetch SOS + + $ wget http://sos.enix.org/wiki-fr/upload/SOSDownload/sos-code-art9.5-lm80.tgz + $ tar xvzf sos-code-art9.5-lm80.tgz + $ cd sos-code-article9.5/ + + b) Patch to support argv/envp + + $ wget http://sos.enix.org/wiki-fr/upload/SOSPatches/patch-art9.5-argv-envp.diff + $ patch -p1 patch-art9.5-argv-envp.diff + + c) Patch with the sample uClibc programs + + $ wget http://thomas.enix.org/pub/uclibc-sos/uclibc-prog-test + $ patch -p1 < uclibc-prog-test + + Edit userland/Makefile, and make sure that UCLIBC_PATH points to + where you have compiled uClibc. + + 5) Compile and test ! + + $ make + $ qemu -fda fd.img -boot a -port-e9 stdio + + In the shell of SOS, run "spawn uclibc-test arg1 arg2 arg3" to run + the simple uClibc program. + +Developping +----------- + +The test program is located in userland/uclibc-test.c. It is linked +statically against the uClibc located in $(UCLIBC_PATH)/libc/libc.a. + +In the uClibc source tree, the sources specific to SOS are available +in libc/sysdeps/sos/. There is one file for each system call in +libc/sysdeps/sos/common.c. + + - Implementation of llseek(). SOS only implements seek64(), so + lseek() is implemented using SOS seek64(). Maybe the implemention + of llseek() in uClibc should be changed ? + + - Missing implementation of fcntl(). + +Compiling Tcc +------------- + +We're trying to get tcc working under SOS. The current status is that +it successfully compiles, you can run "tcc -h" to get the help, but +tcc itself doesn't work, because of the missing implementation of +fcntl() in SOS. + + 1) Download + + $ wget http://fabrice.bellard.free.fr/tcc/tcc-0.9.23.tar.gz + $ tar xvzf tcc-0.9.23.tar.gz + $ cd tcc-0.9.23 + + 2) Compile some more stuff of the uClibc + + Tcc needs more than the libc itself, it also requires libm + (mathematic library) and libdl (dynamic loading of libraries). To + compile them: + + $ cd /path/to/the/uclibc/sources/ + $ make -C ldso + $ make -C libm + + 3) Compile TCC + + Use the following sos-compile.sh script shell (I have not yet + modified the Makefile, feel free to do so, and to send us patches) : + +---------->8--------------->8------------------ +#!/bin/sh + +UCLIBC_PATH=/home/thomas/kos/repository/sos/uclibc-sos/trunk/ +SOS_PATH=/home/thomas/kos/repository/sos/sos-code-uclibc/ + +gcc-3.3 -g -c tcc.c -Wall -nostdinc -I/usr/lib/gcc-lib/i486-linux-gnu/3.3.6/include \ + -I $UCLIBC_PATH/include +ld -nostdlib -T $SOS_PATH/userland/ldscript.lds -o tcc tcc.o \ + $UCLIBC_PATH/libc/misc/internals/__uClibc_main.o \ + $UCLIBC_PATH/libc/sysdeps/sos/i386/crt1.o \ + $UCLIBC_PATH/libc/libc.a \ + $UCLIBC_PATH/ldso/libdl/libdl.a \ + $UCLIBC_PATH/libm/libm.a + +cp tcc $SOS_PATH/userland +---------->8--------------->8------------------ + + Of course, customize SOS_PATH so that it points to the SOS sources, + and UCLIBC_PATH so that it points to your uClibc sources. Then run: + + $ sh sos-compile.sh + + 4) Test in SOS + + The resulting 'tcc' binary has been copied into the userland/ + directory of the SOS sources. To get it integrated to the SOS image, + modify userland/Makefile as follows: + + - userprogs.kimg: $(PROGS) $(UCLIBC_PROGS) + + userprogs.kimg: $(PROGS) $(UCLIBC_PROGS) tcc + + Then, in your SOS sources: + + $ make + $ qemu -fda fd.img -boot a -port-e9 stdio + + In the shell of SOS, you can run "spawn tcc -h", and see the tcc + help. \ Pas de fin de ligne Ă  la fin du fichier. diff -ruN sos/code/sos-code-article9.5/userland/Makefile sos-code-article9.5/userland/Makefile --- sos/code/sos-code-article9.5/userland/Makefile 2006-02-26 19:39:42.000000000 +0100 +++ sos-code-article9.5/userland/Makefile 2006-02-26 20:19:31.000000000 +0100 @@ -24,6 +24,8 @@ LIBGCC = $(shell $(CC) -print-libgcc-file-name) # To benefit from FP/64bits artihm. LDFLAGS = -Wl,--warn-common -nostdlib -Wl,-Tldscript.lds +UCLIBC_PATH=../../uclibc-sos/trunk/ + # Main target all: userprogs.kimg @@ -33,6 +35,8 @@ envtest myprog7 myprog8 myprog9 myprog10 myprog11 myprog12 \ myprog13 myprog14 banner fstest chartest blktest shell +UCLIBC_PROGS := uclibc-test uclibc-test2 + # Build dependencies of the programs init: fstest_utils.o fstest: fstest_utils.o @@ -40,6 +44,7 @@ blktest: fstest_utils.o shell: fstest_utils.o $(PROGS) : % : %.o crt.o crt_asm.o libc.a +$(UCLIBC_PROGS) : % : %.o PWD := $(shell pwd | sed 's/"/\\\"/g;s/\$$/\\\$$/g') @@ -50,8 +55,20 @@ # Generation of the libC libc.a: libc.o string.o stdarg.o debug.o + +GCC_INC:=$(shell $(CC) -print-search-dirs | sed '/^install: /{s/^install: *//;s%\([^ \t:]*\)%-I"\1/include"%g;s/:/ /g;p};d') +uclibc-%.o: uclibc-%.c + $(CC) -g -c $< -Wall -nostdinc $(GCC_INC) -I$(UCLIBC_PATH)/include + +$(UCLIBC_PROGS): + $(LD) -nostdlib -Tldscript.lds -o $@ $< \ + $(UCLIBC_PATH)/libc/misc/internals/__uClibc_main.o \ + $(UCLIBC_PATH)/libc/sysdeps/sos/i386/crt1.o \ + $(UCLIBC_PATH)/libc/libc.a + + # Create a program image to be integrated into the Kernel -userprogs.kimg: $(PROGS) +userprogs.kimg: $(PROGS) $(UCLIBC_PROGS) @echo "# Generating ELF images for inclusion into the kernel image: $@" @echo "SECTIONS { .userprogs . : { " > .userprogs.lds @i=0 ; \ @@ -95,5 +112,5 @@ # Clean directory clean: - $(RM) *.o *.a *~ $(PROGS) *.kimg *.strip + $(RM) *.o *.a *~ $(PROGS) $(UCLIBC_PROGS) *.kimg *.strip $(RM) .userprog* diff -ruN sos/code/sos-code-article9.5/userland/uclibc-test2.c sos-code-article9.5/userland/uclibc-test2.c --- sos/code/sos-code-article9.5/userland/uclibc-test2.c 1970-01-01 01:00:00.000000000 +0100 +++ sos-code-article9.5/userland/uclibc-test2.c 2006-02-26 20:19:31.000000000 +0100 @@ -0,0 +1,7 @@ +#include + +int main(void) +{ + printf ("uclibc-test2 running ... and exiting !\n"); + return 0; +} diff -ruN sos/code/sos-code-article9.5/userland/uclibc-test.c sos-code-article9.5/userland/uclibc-test.c --- sos/code/sos-code-article9.5/userland/uclibc-test.c 1970-01-01 01:00:00.000000000 +0100 +++ sos-code-article9.5/userland/uclibc-test.c 2006-02-26 20:19:32.000000000 +0100 @@ -0,0 +1,285 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BOCHS_IOPORT 0xe9 + +#define bochs_putchar(chr) \ + outb((chr), BOCHS_IOPORT) + +int bochs_putstring(const char* str) +{ + for ( ; str && (*str != '\0') ; str++) + bochs_putchar(*str); + + return 0; +} + +int bochs_printf(const char *format, /* args */...) +{ + char buff[256]; + va_list ap; + + va_start(ap, format); + vsnprintf(buff, sizeof(buff), format, ap); + va_end(ap); + + return bochs_putstring(buff); +} + +int main(int argc, char *argv[]) +{ + int ret; + int fd; + int i; + size_t sz; + char buffer[16]; + FILE *fp; + void *ptr3; + char *ptr1, *ptr2; + off_t off; + + /* + * Use argc / argv + */ + bochs_printf ("argc = %d\n", argc); + for (i = 0; i < argc; i++) + bochs_printf ("argv[%d] = '%s'\n", i, argv[i]); + + /* + * Write on stdout + */ + + bochs_printf ("Welcome in userspace, uClibc powered !\n"); + ret = write (1, "c", 1); + if (ret != 1) { + bochs_printf ("Oops, write failed with %d and errno %d\n", ret, errno); + return ret; + } + printf ("Pouet\n"); + + /* + * Open / write / close a file + */ + + fd = open ("/plop", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if (fd < 0) { + bochs_printf ("Oops, failed to open file, %d errno %d\n", fd, errno); + return ret; + } + + sz = write (fd, "Pouet", strlen("Pouet")); + if (sz != strlen("Pouet")) { + bochs_printf ("Oops, write failed, %d errno %d\n", sz, errno); + return ret; + } + + close(fd); + + /* + * Open / read / close the same file + */ + + fd = open ("/plop", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if (fd < 0) { + bochs_printf ("Oops, failed to open file, %d errno %d\n", fd, errno); + return ret; + } + + memset (buffer, 0, sizeof(buffer)); + sz = read (fd, buffer, sizeof(buffer)); + if (sz < 0) { + bochs_printf ("Oops, read failed, %d errno %d\n", sz, errno); + return ret; + } + + bochs_printf ("Read: %s\n", buffer); + + sz = write (fd, "Meuh", strlen("Meuh")); + if (sz != strlen("Meuh")) { + bochs_printf ("Oops, failed to write, %d errno %d\n", sz, errno); + return ret; + } + + off = lseek (fd, -2, SEEK_CUR); + if (off < 0) { + bochs_printf ("Oops, failed to lseek(), %d errno %d\n", off, errno); + return ret; + } + + memset (buffer, 0, sizeof(buffer)); + sz = read (fd, buffer, sizeof(buffer)); + if (sz < 0) { + bochs_printf ("Oops, read failed, %d errno %d\n", sz, errno); + return ret; + } + + bochs_printf ("Read: %s\n", buffer); + + /* + * Mmap read-only + */ + ptr1 = mmap (NULL, 10, PROT_READ, 0, fd, 0); + if (! ptr1) { + bochs_printf ("Oops, mmap() failed, errno %d\n", errno); + return ret; + } + + bochs_printf ("Mmap mapped @ %p\n", ptr1); + + bochs_printf ("Mmap contents: ptr = %c%c%c%c%c\n", + ptr1[0], ptr1[1], ptr1[2], ptr1[3], ptr1[4]); + + /* + * Uncomment this to test that the program is really killed, because + * the area is read-only (mmap with PROT_READ). + * + * *ptr1 = "B"; + */ + + /* + * Mmap read-write + */ + ptr2 = mmap (NULL, 10, PROT_READ | PROT_WRITE, 0, fd, 0); + if (! ptr2) { + bochs_printf ("Oops, mmap() failed, errno %d\n", errno); + return ret; + } + + bochs_printf ("Mmap mapped @ %p\n", ptr2); + + bochs_printf ("Mmap contents: ptr = %c%c%c%c%c\n", + ptr2[0], ptr2[1], ptr2[2], ptr2[3], ptr2[4]); + + ptr2[0] = 'C'; + + bochs_printf ("Mmap contents after write: ptr = %c%c%c%c%c\n", + ptr2[0], ptr2[1], ptr2[2], ptr2[3], ptr2[4]); + + ret = mprotect (ptr2, 10, PROT_READ); + if (ret != 0) { + bochs_printf ("Oops, mprotect() failed, ret %d errno %d\n", ret, errno); + return ret; + } + + bochs_printf ("Mmap contents after mprotect(PROT_READ): ptr = %c%c%c%c%c\n", + ptr2[0], ptr2[1], ptr2[2], ptr2[3], ptr2[4]); + + /* + * Uncomment this to test that the program is killed because we + * write to an area that has been mprotect(PROT_READ)ed. + * + * ptr2[0] = "D"; + */ + + ret = munmap (ptr2, 10); + if (ret != 0) { + bochs_printf ("Oops, munmap() failed, ret %d errno %d\n", ret, errno); + return ret; + } + + /* + * Uncomment this to test that the program is really killed + * + * ptr2[0] = 'C'; + */ + + ret = munmap (ptr1, 10); + if (ret != 0) { + bochs_printf ("Oops, munmap() failed, ret %d errno %d\n", ret, errno); + return ret; + } + + close(fd); + + /* + * malloc / free tests + */ + + ptr3 = malloc(12); + if (! ptr3) { + bochs_printf ("Oops, malloc() failed, errno %d\n", errno); + return ret; + } + + bochs_printf ("malloc() successful: %p\n", ptr3); + + free (ptr3); + + bochs_printf ("free() worked\n"); + + + ptr3 = malloc(12); + if (! ptr3) { + bochs_printf ("Oops, malloc() failed, errno %d\n", errno); + return ret; + } + + bochs_printf ("malloc() successful: %p\n", ptr3); + + free (ptr3); + + bochs_printf ("free() worked\n"); + + /* + * fopen / fwrite / fclose tests + */ + + fp = fopen("/plip", "w+"); + if (! fp) { + bochs_printf ("Oops, fopen() failed, errno %d\n", errno); + return ret; + } + + bochs_printf ("fopen() successful\n"); + + ret = fwrite ("Taratata", strlen("Taratata"), 1, fp); + if (ret != 1) { + bochs_printf ("Oops, fwrite() failed, %d errno %d\n", sz, errno); + return ret; + } + + ret = fseek (fp, 0, SEEK_SET); + if (ret != 0) { + bochs_printf ("Oops, fseek() failed, %d errno %d\n", ret, errno); + return ret; + } + + memset (buffer, 0, sizeof(buffer)); + ret = fread (buffer, 5, 1, fp); + if (ret != 1) { + bochs_printf ("Oops, fread() failed, %d errno %d\n", ret, errno); + return ret; + } + + bochs_printf ("fread() read '%s'\n", buffer); + + fclose (fp); + + bochs_printf ("getenv(PATH) = %s\n", getenv("PATH")); + + ret = fork(); + if (ret == 0) + { + bochs_printf ("In the child !\n"); + ret = execl ("uclibc-test2", "bonjour", "pouet", NULL); + if (ret != 0) { + bochs_printf ("Cannot exec uclibc-test2, errno %d\n", errno); + } + } + else + { + bochs_printf ("In the parent, child has PID %d\n", ret); + } + + bochs_printf ("Just before exiting in the parent (%p)\n", + __builtin_return_address (0)); + return 0; +}