forked from SerenityOS/serenity
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Start work on a standard C library. I'm calling it... LibC.
- Loading branch information
1 parent
85bcf2e
commit 4cbf079
Showing
8 changed files
with
311 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
|
||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
#include "stdio.h" | ||
#include "stdarg.h" | ||
#include "types.h" | ||
#include <Kernel/Syscall.h> | ||
|
||
template<typename PutChFunc> | ||
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<typename PutChFunc> | ||
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<typename PutChFunc> | ||
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<typename PutChFunc> | ||
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; | ||
} | ||
|
||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#pragma once | ||
|
||
extern "C" { | ||
|
||
int printf(const char* fmt, ...); | ||
int sprintf(char* buffer, const char* fmt, ...); | ||
int putchar(int ch); | ||
|
||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
|
||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
|
||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#include "unistd.h" | ||
#include <Kernel/Syscall.h> | ||
|
||
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); | ||
} | ||
|
||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#pragma once | ||
|
||
#include "types.h" | ||
|
||
extern "C" { | ||
|
||
uid_t getuid(); | ||
gid_t getgid(); | ||
pid_t getpid(); | ||
|
||
} | ||
|