diff --git a/LibC/Makefile b/LibC/Makefile new file mode 100644 index 0000000000..3bf0931624 --- /dev/null +++ b/LibC/Makefile @@ -0,0 +1,32 @@ +OBJS = \ + stdio.o \ + unistd.o + +LIBRARY = LibC.a +ARCH_FLAGS = +STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib +LIBC_FLAGS = -ffreestanding -fno-stack-protector -fno-ident +WARNING_FLAGS = -Wextra -Wall -Wundef -Wcast-qual -Wwrite-strings +FLAVOR_FLAGS = -fomit-frame-pointer -mregparm=3 -march=i386 -m32 -fno-exceptions -fno-rtti -ffunction-sections -fdata-sections -fmerge-all-constants -fno-unroll-loops -falign-functions=1 -falign-jumps=1 -falign-loops=1 -fno-pie -fno-pic +OPTIMIZATION_FLAGS = -Os -fno-asynchronous-unwind-tables +INCLUDE_FLAGS = -I.. -I. + +DEFINES = -DSERENITY_LIBC -DSANITIZE_PTRS + +CXXFLAGS = $(WARNING_FLAGS) $(OPTIMIZATION_FLAGS) $(LIBC_FLAGS) $(FLAVOR_FLAGS) $(ARCH_FLAGS) $(STANDARD_FLAGS) $(INCLUDE_FLAGS) $(DEFINES) +CXX = g++ +LD = ld +AR = ar +LDFLAGS = -T linker.ld --strip-debug -melf_i386 --gc-sections --build-id=none -z norelro -z now + +all: $(LIBRARY) + +$(LIBRARY): $(OBJS) + @echo "LIB $@"; $(AR) rcs $@ $(OBJS) + +.cpp.o: + @echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $< + +clean: + @echo "CLEAN"; rm -f $(LIBRARY) $(OBJS) + diff --git a/LibC/stdarg.h b/LibC/stdarg.h new file mode 100644 index 0000000000..cf3d55977b --- /dev/null +++ b/LibC/stdarg.h @@ -0,0 +1,12 @@ +#pragma once + +extern "C" { + +typedef char* va_list; + +#define va_start(ap, v) ap = (va_list)&v + sizeof(v) +#define va_arg(ap, t) ((t*)(ap += sizeof(t)))[-1] +#define va_end(ap) ap = nullptr + +} + diff --git a/LibC/stdio.cpp b/LibC/stdio.cpp new file mode 100644 index 0000000000..c8b03a9f9e --- /dev/null +++ b/LibC/stdio.cpp @@ -0,0 +1,173 @@ +#include "stdio.h" +#include "stdarg.h" +#include "types.h" +#include + +template +int printHex(PutChFunc putch, char*& bufptr, dword number, byte fields) +{ + static const char h[] = { + '0','1','2','3','4','5','6','7', + '8','9','a','b','c','d','e','f' + }; + + int ret = 0; + byte shr_count = fields * 4; + while (shr_count) { + shr_count -= 4; + putch(bufptr, h[(number >> shr_count) & 0x0F]); + ++ret; + } + return ret; +} + +template +int printNumber(PutChFunc putch, char*& bufptr, dword number) +{ + dword divisor = 1000000000; + char ch; + char padding = 1; + int ret = 0; + + for (;;) { + ch = '0' + (number / divisor); + number %= divisor; + + if (ch != '0') + padding = 0; + + if (!padding || divisor == 1) { + putch(bufptr, ch); + ++ret; + } + + if (divisor == 1) + break; + divisor /= 10; + } + return ret; +} + +template +static int printSignedNumber(PutChFunc putch, char*& bufptr, int number) +{ + if (number < 0) { + putch(bufptr, '-'); + return printNumber(putch, bufptr, 0 - number) + 1; + } + return printNumber(putch, bufptr, number); +} + +static void sys_putch(char*, char ch) +{ + Syscall::invoke(Syscall::PutCharacter, ch); +} + +template +int printfInternal(PutChFunc putch, char* buffer, const char*& fmt, char*& ap) +{ + const char *p; + + int ret = 0; + char* bufptr = buffer; + + for (p = fmt; *p; ++p) { + if (*p == '%' && *(p + 1)) { + ++p; + switch( *p ) + { + case 's': + { + const char* sp = va_arg(ap, const char*); + //ASSERT(sp != nullptr); + if (!sp) { + putch(bufptr, '('); + putch(bufptr, 'n'); + putch(bufptr, 'u'); + putch(bufptr, 'l'); + putch(bufptr, 'l'); + putch(bufptr, ')'); + ret += 6; + } else { + for (; *sp; ++sp) { + putch(bufptr, *sp); + ++ret; + } + } + } + break; + + case 'd': + ret += printSignedNumber(putch, bufptr, va_arg(ap, int)); + break; + + case 'u': + ret += printNumber(putch, bufptr, va_arg(ap, dword)); + break; + + case 'x': + ret += printHex(putch, bufptr, va_arg(ap, dword), 8); + break; + + case 'w': + ret += printHex(putch, bufptr, va_arg(ap, int), 4); + break; + + case 'b': + ret += printHex(putch, bufptr, va_arg(ap, int), 2); + break; + + case 'c': + putch(bufptr, (char)va_arg(ap, int)); + ++ret; + break; + + case 'p': + putch(bufptr, '0'); + putch(bufptr, 'x'); + ret += 2; + ret += printHex(putch, bufptr, va_arg(ap, dword), 8); + break; + } + } + else { + putch(bufptr, *p); + ++ret; + } + } + return ret; +} + +extern "C" { + +int putchar(int ch) +{ + return ch; +} + +int printf(const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + int ret = printfInternal(sys_putch, nullptr, fmt, ap); + va_end(ap); + return ret; +} + +static void buffer_putch(char*& bufptr, char ch) +{ + *bufptr++ = ch; +} + +int sprintf(char* buffer, const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + int ret = printfInternal(buffer_putch, buffer, fmt, ap); + buffer[ret] = '\0'; + va_end(ap); + return ret; +} + +} + diff --git a/LibC/stdio.h b/LibC/stdio.h new file mode 100644 index 0000000000..b34e0828da --- /dev/null +++ b/LibC/stdio.h @@ -0,0 +1,10 @@ +#pragma once + +extern "C" { + +int printf(const char* fmt, ...); +int sprintf(char* buffer, const char* fmt, ...); +int putchar(int ch); + +} + diff --git a/LibC/syscall.h b/LibC/syscall.h new file mode 100644 index 0000000000..f702dbbc4e --- /dev/null +++ b/LibC/syscall.h @@ -0,0 +1,36 @@ +#pragma once + +#include "types.h" + +extern "C" { + +inline dword syscall_a0(dword function) +{ + dword result; + asm volatile("int $0x80":"=a"(result):"a"(function)); + return result; +} + +inline dword syscall_a1(dword function, dword arg1) +{ + dword result; + asm volatile("int $0x80":"=a"(result):"a"(function),"d"(arg1)); + return result; +} + +inline dword syscall_a2(dword function, dword arg1, dword arg2) +{ + dword result; + asm volatile("int $0x80":"=a"(result):"a"(function),"d"(arg1),"c"(arg2)); + return result; +} + +inline dword syscall_a3(dword function, dword arg1, dword arg2, dword arg3) +{ + dword result; + asm volatile("int $0x80":"=a"(result):"a"(function),"d"(arg1),"c"(arg2),"b"(arg3)); + return result; +} + +} + diff --git a/LibC/types.h b/LibC/types.h new file mode 100644 index 0000000000..5bb4538f41 --- /dev/null +++ b/LibC/types.h @@ -0,0 +1,14 @@ +#pragma once + +extern "C" { + +typedef unsigned int dword; +typedef unsigned short word; +typedef unsigned char byte; + +typedef dword uid_t; +typedef dword gid_t; +typedef dword pid_t; + +} + diff --git a/LibC/unistd.cpp b/LibC/unistd.cpp new file mode 100644 index 0000000000..2a7efa95c2 --- /dev/null +++ b/LibC/unistd.cpp @@ -0,0 +1,22 @@ +#include "unistd.h" +#include + +extern "C" { + +uid_t getuid() +{ + return Syscall::invoke(Syscall::PosixGetuid); +} + +uid_t getgid() +{ + return Syscall::invoke(Syscall::PosixGetgid); +} + +uid_t getpid() +{ + return Syscall::invoke(Syscall::PosixGetpid); +} + +} + diff --git a/LibC/unistd.h b/LibC/unistd.h new file mode 100644 index 0000000000..bffc5840b5 --- /dev/null +++ b/LibC/unistd.h @@ -0,0 +1,12 @@ +#pragma once + +#include "types.h" + +extern "C" { + +uid_t getuid(); +gid_t getgid(); +pid_t getpid(); + +} +