Navigation Menu

Skip to content

Commit

Permalink
Updates to gitignore, Makefile, README, STATS. Cleaned up t/ for `-…
Browse files Browse the repository at this point in the history
…ansi -Wall -pedantic`. Added `_end` & friends segment pointers, and tests for `_end` & a basic implementation of `sys_brk`, `sbrk` and `brk` as a test (malloc should be a snap to write now)
  • Loading branch information
lpsantil committed Oct 9, 2015
1 parent 7e5dead commit eaf696a
Show file tree
Hide file tree
Showing 16 changed files with 386 additions and 111 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -32,3 +32,5 @@
*.pid
*.tmp
*.footprint
*.log
*.d
11 changes: 7 additions & 4 deletions Makefile
Expand Up @@ -25,9 +25,10 @@ endif
######################################################################

# Comment next line if you want System Default/GNU BFD LD instead
LD = gold
CFLAGS ?= -Os -nostdlib -fomit-frame-pointer
LDFLAGS ?= -s -nostdlib
#LD = gold
CFLAGS ?= -Os -Wall -ansi -pedantic -nostdlib -fomit-frame-pointer -fno-stack-protector -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-unroll-loops -fmerge-all-constants -fno-ident -mfpmath=387 -mfancy-math-387 -ffunction-sections -fdata-sections -Wl,--gc-sections
LDFLAGS ?= -s -nostdlib -z norelro --hash-style=sysv --build-id=none --gc-sections
#LDFLAGS ?= -g -nostdlib
#LDFLAGS ?= -s -nostdlib -Wl,--gc-sections

DDIR = docs
Expand Down Expand Up @@ -59,6 +60,8 @@ TMPCI = $(shell cat tmp.ci.pid)
TMPCT = $(shell cat tmp.ct.pid)
TMPCD = $(shell cat tmp.cd.pid)

CILOG ?= tmp.ci.log

# DEPS
DEPS =
LIBDEP =
Expand Down Expand Up @@ -118,7 +121,7 @@ runtest: $(TEXE)
for T in $^ ; do $(TAP) $$T ; done

start_ci:
watch time -p make clean all & echo $$! > tmp.ci.pid
( watch time -p make clean all ) &> $(CILOG) & echo $$! > tmp.ci.pid

stop_ci:
kill -9 $(TMPCI)
Expand Down
26 changes: 19 additions & 7 deletions README.md
Expand Up @@ -2,15 +2,16 @@
A minimal C runtime for Linux on i386 & x86_64

## Features
* Implemented in just 195 SLOC of C code.
* Implemented in just 202 SLOC of C code.
* Just 9 lines of GCC inline ASM for i386, or,
* Just 6 lines GCC inline ASM for x86_64
* Small runtime providing just `argc`, `argv`, `envp`, `__environ`, `errno`, `_exit`, and `syscall0/1/2/3/4/5/6`
* Uses [gold][19] (Google LD, part of GNU Binutils) instead of GNU ld to save 100-200 bytes at static link time
* Hello World in just 1140 bytes (i386) or 1328 bytes (x86_64)
* Small runtime providing just `argc`, `argv`, `envp`, `__environ`, `errno`, `_exit`, `_end`, `_edata`, `_etext`, `__executable_start` and `syscall0/1/2/3/4/5/6`
* An example implementation of `sys_brk`, `brk`, and `sbrk`
* Can be used with [gold][19] (Google LD, part of GNU Binutils)
* Hello World in just 608 bytes (i386) or 792 bytes (x86_64)
* Small binary sizes vs. other libc's

See STATS.md to see how rt0 fares.
See [STATS.md][20] to see how rt0 fares.
See the [musl libc comparison][0] to see how other libc's fare.

## Building
Expand All @@ -21,15 +22,17 @@ Try:
* `make runtest`
* `make DESTDIR=/usr/local install`, or simply, `make install`
* You can also do `make uninstall`
* It is highly recommended that you build using `WITH_FAST_SYSCALL=1`, e.g., `make WITH_FAST_SYSCALL=1`

## Usage
* Include `rt0/rt0.h` for `__environ`, `_exit`
* Include `rt0/syscall.h` for `SYS_*`, `syscall0/1/2/3/4/5/6`
* Define `main` as `int main( int, char**, char** )`
* Compile your code with `-nostdlib`, e.g., `cc -c prog.c -nostdlib -o prog.o`
* Compile your code with at least `-nostdlib`, e.g., `cc -c prog.c -nostdlib -o prog.o`
* On Linux, link with librt0, e.g., `cc prog.o -nostdlib -lrt0 -o prog`
* On FreeBSD, link with librt0 using, `cc prog.o -Wl,-u_start -nostdlib -lrt0 -o prog`
* To enable GNU ld, type `make LD=ld`
* To enable Google ld, type `make LD=gold`
* To enable GNU ld, type `make LD=ld` (default)
* To enable a slightly faster version of the syscalls, type `make WITH_FAST_SYSCALL=1`
* To enable `-fdata-sections -ffunction-sections`, type `make WITH_SECTIONS=1`
* To enable a debug build, type `make WITH_DEBUG=1`
Expand All @@ -43,6 +46,10 @@ Try:
* [System V ABI/Calling Convention][6]
* [Linux syscall interface][7]
* [gold - Google ld][19]
* [brk(2) man page][21]
* [malloc implementation@Stack Overflow][22]
* [A Quick Tutorial on Implementing and Debugging Malloc, Free, Calloc, and Realloc][23]
* [Tips of malloc & free][24]

## Other small libc's and runtimes
* [musl libc][8]
Expand Down Expand Up @@ -77,3 +84,8 @@ Try:
[17]: http://www.fefe.de/djb/
[18]: https://gist.github.com/lunixbochs/462ee21c3353c56b910f
[19]: http://en.wikipedia.org/wiki/Gold_%28linker%29
[20]: https://github.com/lpsantil/rt0/blob/master/STATS.md
[21]: http://linux.die.net/man/2/brk
[22]: http://stackoverflow.com/questions/5422061/malloc-implementation
[23]: http://danluu.com/malloc-tutorial/
[24]: http://elinux.org/images/b/b5/Elc2013_Kobayashi.pdf
63 changes: 43 additions & 20 deletions STATS.md
@@ -1,23 +1,46 @@
# rt0 library & binary sizes

| Binary | Arch | Size | Purpose | Compile Args |
-------------:|:-------|-----:|:-------------------------|:--------------------------------------|
| librt0.a | i386 | 3502 | Startup code+syscall | -Os -nostdlib -fomit-frame-pointer |
| librt0.a | x86_64 | 4798 | Startup code+syscall | -Os -nostdlib -fomit-frame-pointer |
| t/hello.exe | i386 | 1140 | Hello World\n | -Os -s -nostdlib -fomit-frame-pointer |
| t/hello.exe | x86_64 | 1328 | Hello World\n | -Os -s -nostdlib -fomit-frame-pointer |
| hello.exe | i386 | 5532 | Hello World\n with glibc | -Os -s -fomit-frame-pointer |
| hello.exe | x86_64 | 6240 | Hello World\n with glibc | -Os -s -fomit-frame-pointer |
| t/null.exe | i386 | 1044 | Empty main | -Os -s -nostdlib -fomit-frame-pointer |
| t/null.exe | x86_64 | 1272 | Empty main | -Os -s -nostdlib -fomit-frame-pointer |
| null.exe | i386 | 5528 | Empty main | -Os -s -fomit-frame-pointer |
| null.exe | x86_64 | 6232 | Empty main | -Os -s -fomit-frame-pointer |
| ... | ... | ... | ... | With `__RT0_WITH_FASTER_SYSCALL__` |
| librt0.a | i386 | 4168 | Startup code+syscall | -Os -nostdlib -fomit-frame-pointer |
| librt0.a | x86_64 | 5660 | Startup code+syscall | -Os -nostdlib -fomit-frame-pointer |
| t/hello.exe | i386 | 1440 | Hello World\n | -Os -s -nostdlib -fomit-frame-pointer |
| t/hello.exe | x86_64 | 1600 | Hello World\n | -Os -s -nostdlib -fomit-frame-pointer |
| t/null.exe | i386 | 1368 | Empty main | -Os -s -nostdlib -fomit-frame-pointer |
| t/null.exe | x86_64 | 1560 | Empty main | -Os -s -nostdlib -fomit-frame-pointer |
| Binary | Arch | Size | Purpose |
-------------:|:-------|-----:|:-----------------------------------|
| librt0.a | i386 | 2810 | Startup code+syscall |
| librt0.a | x86_64 | 3974 | Startup code+syscall |
| t/hello.exe | i386 | 624 | Hello World\n |
| t/hello.exe | x86_64 | 824 | Hello World\n |
| hello.exe | i386 | 2988 | Hello World\n with glibc |
| hello.exe | x86_64 | 4200 | Hello World\n with glibc |
| t/null.exe | i386 | 560 | Empty main |
| t/null.exe | x86_64 | 768 | Empty main |
| null.exe | i386 | 2888 | Empty main with glibc |
| null.exe | x86_64 | 2988 | Empty main with glibc |
| ... | ... | ... | With `__RT0_WITH_FASTER_SYSCALL__` |
| librt0.a | i386 | 3980 | Startup code+syscall |
| librt0.a | x86_64 | 5604 | Startup code+syscall |
| t/hello.exe | i386 | 608 | Hello World\n |
| t/hello.exe | x86_64 | 792 | Hello World\n |
| t/null.exe | i386 | 552 | Empty main |
| t/null.exe | x86_64 | 752 | Empty main |

Compiler: GCC 4.8.2, gold linker 1.11 (binutils 2.24) OS: Ubuntu 14.04.2, Source: Author
Compiler: GCC 4.8.4, gold linker 1.11, ld/binutils 2.24, OS: Ubuntu 14.04.3, Source: Author
Compile Flags: `-Os -nostdlib -fomit-frame-pointer -fno-stack-protector -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-unroll-loops -fmerge-all-constants -fno-ident -mfpmath=387 -mfancy-math-387 -ffunction-sections -fdata-sections Wl,--gc-sections`
Link Flags: `-s -nostdlib -z norelro --hash-style=sysv --build-id=none --gc-sections`

`HelloWorld` & `null` compiled with flags above but without `-nostdlib`.

`HelloWorld.glibc.c`
```
#include <unistd.h>
int main( int argc, char** argv, char** envp )
{
int ret = write( 1, "Hello World!\n", 13 );
return( 0 );
}
```

`null.glibc.c`
```
int main( int argc, char** argv, char** envp )
{
return( 0 );
}
```
1 change: 1 addition & 0 deletions include/rt0/rt0.h
Expand Up @@ -8,6 +8,7 @@

extern char **__environ; /* pointer to array of char * strings that define the current environment variables */
extern int errno;
extern char _end, _edata, _etext, __executable_start;

void _exit( int r ) __attribute__((noreturn));
/*
Expand Down
34 changes: 34 additions & 0 deletions lib/.gitignore
@@ -0,0 +1,34 @@
# Object files
*.o
*.ko
*.obj
*.elf

# Precompiled Headers
*.gch
*.pch

# Libraries
*.lib
*.a
*.la
*.lo

# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib

# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex

# Temporary files
*.pid
*.tmp
*.footprint
73 changes: 73 additions & 0 deletions t/_end.c
@@ -0,0 +1,73 @@
#include <rt0/syscall.h>

int write( int f, const char* d, int l )
{
int ret = syscall3( SYS_write, f, ( long )( d ), l );

return( ret );
}

int str_len( const char *string )
{
int length = 0;
while( *string ) { string++; length++; }
return length;
}

void print( const char* string )
{
write( 1, string, str_len( string ) );
}

void printLongHex( long i )
{
char* nums = "0123456789ABCDEF";
long d = 1,
r;

if( i < 0 )
{
print( "-" );

printLongHex( -i );

return;
}

d = i / 16;
r = i % 16;

if( d != 0 )
{
printLongHex( d );
}

write( 1, &( nums[ r ] ), 1 );
}

int main( int argc, char **argv, char **envp )
{
long addr;

addr = ( long )( &__executable_start );
print( "Address of __executable_start: " );
printLongHex( addr );
print( "\n" );

addr = ( long )( &_etext );
print( "Address of _etext: " );
printLongHex( addr );
print( "\n" );

addr = ( long )( &_edata );
print( "Address of _edata: " );
printLongHex( addr );
print( "\n" );

addr = ( long )( &_end );
print( "Address of _end: " );
printLongHex( addr );
print( "\n" );

return( 0 );
}
28 changes: 14 additions & 14 deletions t/argc.c
@@ -1,5 +1,19 @@
#include <rt0/syscall.h>

int write( int f, const char* d, int l )
{
int ret = syscall3( SYS_write, f, ( long )( d ), l );

return( ret );
}

int str_len( const char *string )
{
int length = 0;
while( *string ) { string++; length++; }
return length;
}

void print( const char* string )
{
write( 1, string, str_len( string ) );
Expand Down Expand Up @@ -39,17 +53,3 @@ int main( int argc, char** argv, char** envp )

return( 0 );
}

int write( int f, char* d, int l )
{
int ret = syscall3( SYS_write, f, ( long )( d ), l );

return( ret );
}

int str_len( const char *string )
{
int length = 0;
while( *string ) { string++; length++; }
return length;
}
28 changes: 14 additions & 14 deletions t/argv.c
@@ -1,5 +1,19 @@
#include <rt0/syscall.h>

int write( int f, const char* d, int l )
{
int ret = syscall3( SYS_write, f, ( long )( d ), l );

return( ret );
}

int str_len( const char *string )
{
int length = 0;
while( *string ) { string++; length++; }
return length;
}

void print( const char* string )
{
write( 1, string, str_len( string ) );
Expand All @@ -19,17 +33,3 @@ int main( int argc, char** argv, char** envp )

return( 0 );
}

int write( int f, char* d, int l )
{
int ret = syscall3( SYS_write, f, ( long )( d ), l );

return( ret );
}

int str_len( const char *string )
{
int length = 0;
while( *string ) { string++; length++; }
return length;
}
28 changes: 14 additions & 14 deletions t/envp.c
@@ -1,5 +1,19 @@
#include <rt0/syscall.h>

int write( int f, const char* d, int l )
{
int ret = syscall3( SYS_write, f, ( long )( d ), l );

return( ret );
}

int str_len( const char *string )
{
int length = 0;
while( *string ) { string++; length++; }
return length;
}

void println( const char* string )
{
write( 1, string, str_len( string ) );
Expand All @@ -20,17 +34,3 @@ int main( int argc, char** argv, char** envp )

return( 0 );
}

int write( int f, char* d, int l )
{
int ret = syscall3( SYS_write, f, ( long )( d ), l );

return( ret );
}

int str_len( const char *string )
{
int length = 0;
while( *string ) { string++; length++; }
return length;
}

0 comments on commit eaf696a

Please sign in to comment.