From 72ffbdee0d5d28ba3d44ed3b19ce0c95c4285152 Mon Sep 17 00:00:00 2001 From: Furkan Mudanyali Date: Mon, 18 Jul 2022 16:42:25 +0300 Subject: [PATCH] vprintf, stpcpy, strcpy, strcat, ssp, isdigit --- kernel/Makefile | 2 +- kernel/kernel/kernel.c | 7 +- libc/Makefile | 8 +- libc/ctype/isdigit.c | 6 + libc/include/ctype.h | 14 ++ libc/include/ssp.h | 9 + libc/include/stdio.h | 2 + libc/include/string.h | 4 + libc/ssp/ssp.c | 20 ++ libc/stdio/printf.c | 90 +------- libc/stdio/vprintf.c | 454 +++++++++++++++++++++++++++++++++++++++++ libc/string/stpcpy.c | 13 ++ libc/string/strcat.c | 6 + libc/string/strcpy.c | 6 + 14 files changed, 554 insertions(+), 87 deletions(-) create mode 100644 libc/ctype/isdigit.c create mode 100644 libc/include/ctype.h create mode 100644 libc/include/ssp.h create mode 100644 libc/ssp/ssp.c create mode 100644 libc/stdio/vprintf.c create mode 100644 libc/string/stpcpy.c create mode 100644 libc/string/strcat.c create mode 100644 libc/string/strcpy.c diff --git a/kernel/Makefile b/kernel/Makefile index 9f9e3e8..448c0b6 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -13,7 +13,7 @@ EXEC_PREFIX?=$(PREFIX) BOOTDIR?=$(EXEC_PREFIX)/boot INCLUDEDIR?=$(PREFIX)/include -CFLAGS:=$(CFLAGS) -ffreestanding -Wall -Wextra +CFLAGS:=$(CFLAGS) -ffreestanding -Wall -Wextra -fstack-protector CPPFLAGS:=$(CPPFLAGS) -D__is_kernel -Iinclude LDFLAGS:=$(LDFLAGS) LIBS:=$(LIBS) -nostdlib -lk -lgcc diff --git a/kernel/kernel/kernel.c b/kernel/kernel/kernel.c index 7a752a6..6ef89b7 100644 --- a/kernel/kernel/kernel.c +++ b/kernel/kernel/kernel.c @@ -4,5 +4,10 @@ void kernel_main(void) { terminal_initialize(); - printf("Hello, kernel World!\n"); + printf("Hello, kernel World!\n "); + printf("String test: %s\n ", "HELLOOOOO"); + printf("Float test: %.10f\n ", 0.123456789); + printf("Int test: %d\n ", 747474); + printf("Hex test: 0x%x\n ", 0xDEADBEEF); + printf("And now for 0.1 + 0.2...... which is: %.17f\n", 0.1 + 0.2); } diff --git a/libc/Makefile b/libc/Makefile index ce70b46..49639af 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -13,7 +13,7 @@ EXEC_PREFIX?=$(PREFIX) INCLUDEDIR?=$(PREFIX)/include LIBDIR?=$(EXEC_PREFIX)/lib -CFLAGS:=$(CFLAGS) -ffreestanding -Wall -Wextra +CFLAGS:=$(CFLAGS) -ffreestanding -Wall -Wextra -fstack-protector CPPFLAGS:=$(CPPFLAGS) -D__is_libc -Iinclude LIBK_CFLAGS:=$(CFLAGS) LIBK_CPPFLAGS:=$(CPPFLAGS) -D__is_libk @@ -29,10 +29,16 @@ LIBK_CPPFLAGS:=$(LIBK_CPPFLAGS) $(KERNEL_ARCH_CPPFLAGS) FREEOBJS=\ $(ARCH_FREEOBJS) \ +ssp/ssp.o \ +ctype/isdigit.o \ +stdio/vprintf.o \ stdio/printf.o \ stdio/putchar.o \ stdio/puts.o \ stdlib/abort.o \ +string/stpcpy.o \ +string/strcpy.o \ +string/strcat.o \ string/memcmp.o \ string/memcpy.o \ string/memmove.o \ diff --git a/libc/ctype/isdigit.c b/libc/ctype/isdigit.c new file mode 100644 index 0000000..69c05ad --- /dev/null +++ b/libc/ctype/isdigit.c @@ -0,0 +1,6 @@ +#include +#undef isdigit + +int isdigit(int c) { + return (unsigned)c-'0' < 10; +} diff --git a/libc/include/ctype.h b/libc/include/ctype.h new file mode 100644 index 0000000..1133c97 --- /dev/null +++ b/libc/include/ctype.h @@ -0,0 +1,14 @@ +#ifndef _CTYPE_H +#define _CTYPE_H + +#ifdef __cplusplus +extern "C" { +#endif + +int isdigit(int); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libc/include/ssp.h b/libc/include/ssp.h new file mode 100644 index 0000000..3bd75d8 --- /dev/null +++ b/libc/include/ssp.h @@ -0,0 +1,9 @@ +#ifndef _SSP_H +#define _SSP_H + +#include + +extern uintptr_t __stack_chk_guard; +void __stack_chk_fail(void); + +#endif diff --git a/libc/include/stdio.h b/libc/include/stdio.h index b3be14e..0931ce9 100644 --- a/libc/include/stdio.h +++ b/libc/include/stdio.h @@ -2,6 +2,7 @@ #define _STDIO_H 1 #include +#include #define EOF (-1) @@ -9,6 +10,7 @@ extern "C" { #endif +int vprintf(const char *, va_list); int printf(const char* __restrict, ...); int putchar(int); int puts(const char*); diff --git a/libc/include/string.h b/libc/include/string.h index 31a6266..709e37d 100644 --- a/libc/include/string.h +++ b/libc/include/string.h @@ -8,6 +8,10 @@ extern "C" { #endif +char* __stpcpy(char* __restrict, const char* __restrict); +char* strcpy(char* __restrict, const char* __restrict); +char* strcat(char* __restrict, const char* __restrict); + int memcmp(const void*, const void*, size_t); void* memcpy(void* __restrict, const void* __restrict, size_t); void* memmove(void*, const void*, size_t); diff --git a/libc/ssp/ssp.c b/libc/ssp/ssp.c new file mode 100644 index 0000000..c18c769 --- /dev/null +++ b/libc/ssp/ssp.c @@ -0,0 +1,20 @@ +#include +#include +#include + +#if UINT32_MAX == UINTPTR_MAX +#define STACK_CHK_GUARD 0x74316974 +#else +#define STACK_CHK_GUARD 0x7431697474316974 +#endif + +uintptr_t __stack_chk_guard = STACK_CHK_GUARD; + +__attribute__((noreturn)) +void __stack_chk_fail(void){ +#if __STDC_HOSTED__ + abort(); +#elif __is_rockos_kernel + panic("Stack smashing detected!"); +#endif +} diff --git a/libc/stdio/printf.c b/libc/stdio/printf.c index dff217d..115fc08 100644 --- a/libc/stdio/printf.c +++ b/libc/stdio/printf.c @@ -1,88 +1,10 @@ -#include -#include #include #include -#include -static bool print(const char* data, size_t length) { - const unsigned char* bytes = (const unsigned char*) data; - for (size_t i = 0; i < length; i++) { - if (putchar(bytes[i]) == EOF) { - return false; - } - } - return true; -} - -int printf(const char* restrict format, ...) { - va_list parameters; - va_start(parameters, format); - - int written = 0; - - while (*format != '\0') { - size_t maxrem = INT_MAX - written; - - if (format[0] != '%' || format[1] == '%') { - if (format[0] == '%') { - format++; - } - size_t amount = 1; - while (format[amount] && format[amount] != '%') { - amount++; - } - if (maxrem < amount) { - // TODO: Set errno to EOVERFLOW. - return -1; - } - if (!print(format, amount)) { - return -1; - } - format += amount; - written += amount; - continue; - } - - const char* format_begun_at = format++; - - if (*format == 'c') { - format++; - char c = (char) va_arg(parameters, int); - if (!maxrem) { - // TODO: Set errno to EOVERFLOW - return -1; - } - if (!print(&c, sizeof(c))) { - return -1; - } - written++; - } else if (*format == 's') { - format ++; - const char* str = va_arg(parameters, const char*); - size_t len = strlen(str); - if (maxrem < len) { - // TODO: Set errno to EOVERFLOW - return -1; - } - if (!print(str, len)) { - return -1; - } - written += len; - } else { - format = format_begun_at; - size_t len = strlen(format); - if (maxrem < len) { - // TODO: Set errno to EOVERFLOW - return -1; - } - if (!print(format, len)) { - return -1; - } - written += len; - format += len; - } - } - - va_end(parameters); - return written; +__attribute__ ((format (printf, 1, 2))) int printf(const char* format, ...) { + va_list list; + va_start(list, format); + int ret = vprintf(format, list); + va_end(list); + return ret; } diff --git a/libc/stdio/vprintf.c b/libc/stdio/vprintf.c new file mode 100644 index 0000000..2e309ae --- /dev/null +++ b/libc/stdio/vprintf.c @@ -0,0 +1,454 @@ +#include +#include +#include +#include +#include +#include +#include + +char* __int_str(intmax_t i, char* b, int base, bool plusSign, bool spaceSign, int paddingNo, bool justify, bool zeroPad) { + char digit[32] = {0}; + memset(digit, 0, 32); + strcpy(digit, "0123456789"); + + switch(base){ + case 16: + strcat(digit, "ABCDEF"); + break; + case 17: + strcat(digit, "abcdef"); + base = 16; + break; + } + + char* p = b; + if (i < 0) { + *p++ = '-'; + } else if (plusSign) { + *p++ = '+'; + } else if (!plusSign && spaceSign) { + *p++ = ' '; + } + + intmax_t shifter = i; + do { + ++p; + shifter = shifter / base; + } while (shifter); + + *p = '\0'; + do { + *--p = digit[i % base]; + i = i / base; + } while (i); + + int padding = paddingNo - (int)strlen(b); + if (padding < 0) { + padding = 0; + } + + if (justify) { + while (padding--) { + if (zeroPad) { + b[strlen(b)] = '0'; + } else { + b[strlen(b)] = ' '; + } + } + } else { + char a[256] = {0}; + while (padding--) { + if (zeroPad) { + a[strlen(a)] = '0'; + } else { + a[strlen(a)] = ' '; + } + } + strcat(a, b); + strcpy(b, a); + } + + return b; +} + +void displayCharacter(char c, int* a) { + putchar(c); + *a += 1; +} + +void displayString(char* c, int* a) { + for (int i = 0; c[i]; ++i) { + displayCharacter(c[i], a); + } +} + +int vprintf(const char* format, va_list list) { + int chars = 0; + char intStrBuffer[256] = {0}; + + for(int i = 0; format[i]; ++i) { + char specifier = '\0'; + char length = '\0'; + + int lengthSpec = 0; + int precSpec = 0; + int expo = 0; + + bool leftJustify = false; + bool zeroPad = false; + bool spaceNoSign = false; + bool altForm = false; + bool plusSign = false; + bool emode = false; + + if(format[i] == '%') { + ++i; + bool extBreak = false; + for(;;){ + switch(format[i]) { + case '-': + leftJustify = true; + ++i; + break; + case '+': + plusSign = true; + ++i; + break; + case '#': + altForm = true; + ++i; + break; + case ' ': + spaceNoSign = true; + ++i; + break; + case '0': + zeroPad = true; + ++i; + break; + default: + extBreak = true; + break; + } + if (extBreak) break; + } + + while(isdigit(format[i])) { + lengthSpec *= 10; + lengthSpec += format[i] - 48; + ++i; + } + + if(format[i] == '*') { + lengthSpec = va_arg(list, int); + ++i; + } + + if(format[i] == '.') { + ++i; + while(isdigit(format[i])) { + precSpec *= 10; + precSpec += format[i] - 48; + ++i; + } + + if(format[i] == '*') { + precSpec = va_arg(list, int); + ++i; + } + } else { + precSpec = 6; + } + + if(format[i] == 'h' || format[i] == 'l' || format[i] == 'j' || format[i] == 'z' || format[i] == 't' || format[i] == 'L') { + length = format[i]; + ++i; + if (format[i] == 'h') { + length = 'H'; + } else if (format[i] == 'l') { + length = 'q'; + ++i; + } + } + specifier = format[i]; + + memset(intStrBuffer, 0, 256); + + int base = 10; + if (specifier == 'o') { + base = 8; + specifier = 'u'; + if (altForm) { + displayString("0", &chars); + } + } + if (specifier == 'p') { + base = 16; + length = 'z'; + specifier = 'u'; + } + switch (specifier) { + case 'X': + base = 16; + case 'x': + base = base == 10 ? 17 : base; + if (altForm) { + displayString("0x", &chars); + } + case 'u': + { + switch (length) { + case 0: + { + unsigned int integer = va_arg(list, unsigned int); + __int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad); + displayString(intStrBuffer, &chars); + break; + } + case 'H': + { + unsigned char integer = (unsigned char)va_arg(list, unsigned int); + __int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad); + displayString(intStrBuffer, &chars); + break; + } + case 'h': + { + unsigned short int integer = va_arg(list, unsigned int); + __int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad); + displayString(intStrBuffer, &chars); + break; + } + case 'l': + { + unsigned long integer = va_arg(list, unsigned long); + __int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad); + displayString(intStrBuffer, &chars); + break; + } + case 'q': + { + unsigned long long integer = va_arg(list, unsigned long long); + __int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad); + displayString(intStrBuffer, &chars); + break; + } + case 'j': + { + uintmax_t integer = va_arg(list, uintmax_t); + __int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad); + displayString(intStrBuffer, &chars); + break; + } + case 'z': + { + size_t integer = va_arg(list, size_t); + __int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad); + displayString(intStrBuffer, &chars); + break; + } + case 't': + { + ptrdiff_t integer = va_arg(list, ptrdiff_t); + __int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad); + displayString(intStrBuffer, &chars); + break; + } + default: + break; + } + break; + } + + case 'd': + case 'i': + { + switch (length) { + case 0: + { + unsigned int integer = va_arg(list, unsigned int); + __int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad); + displayString(intStrBuffer, &chars); + break; + } + case 'H': + { + unsigned char integer = (unsigned char)va_arg(list, unsigned int); + __int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad); + displayString(intStrBuffer, &chars); + break; + } + case 'h': + { + unsigned short int integer = va_arg(list, unsigned int); + __int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad); + displayString(intStrBuffer, &chars); + break; + } + case 'l': + { + unsigned long integer = va_arg(list, unsigned long); + __int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad); + displayString(intStrBuffer, &chars); + break; + } + case 'q': + { + unsigned long long integer = va_arg(list, unsigned long long); + __int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad); + displayString(intStrBuffer, &chars); + break; + } + case 'j': + { + uintmax_t integer = va_arg(list, uintmax_t); + __int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad); + displayString(intStrBuffer, &chars); + break; + } + case 'z': + { + size_t integer = va_arg(list, size_t); + __int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad); + displayString(intStrBuffer, &chars); + break; + } + case 't': + { + ptrdiff_t integer = va_arg(list, ptrdiff_t); + __int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad); + displayString(intStrBuffer, &chars); + break; + } + default: + break; + } + break; + } + + case 'c': + { + if (length == 'l') { + displayCharacter(va_arg(list, wchar_t), &chars); + } else { + displayCharacter(va_arg(list, int), &chars); + } + break; + } + + case 's': + { + displayString(va_arg(list, char*), &chars); + break; + } + + case 'n': + { + switch (length) { + case 'H': + *(va_arg(list, signed char*)) = chars; + break; + case 'h': + *(va_arg(list, short int*)) = chars; + break; + + case 0: + { + int* a = va_arg(list, int*); + *a = chars; + break; + } + + case 'l': + *(va_arg(list, long*)) = chars; + break; + case 'q': + *(va_arg(list, long long*)) = chars; + break; + case 'j': + *(va_arg(list, intmax_t*)) = chars; + break; + case 'z': + *(va_arg(list, size_t*)) = chars; + break; + case 't': + *(va_arg(list, ptrdiff_t*)) = chars; + break; + default: + break; + } + break; + } + + case 'e': + case 'E': + emode = true; + + case 'f': + case 'F': + case 'g': + case 'G': + { + double floating = va_arg(list, double); + + while (emode && floating >= 10) { + floating /= 10; + ++expo; + } + + int form = lengthSpec - precSpec - expo - (precSpec || altForm ? 1 : 0); + if (emode) { + form -= 4; // 'e+00' + } + if (form < 0) { + form = 0; + } + + __int_str(floating, intStrBuffer, base, plusSign, spaceNoSign, form, leftJustify, zeroPad); + + displayString(intStrBuffer, &chars); + + floating -= (int) floating; + + for(int i = 0; i < precSpec; ++i) { + floating *= 10; + } + intmax_t decPlaces = (intmax_t)(floating +0.5); + + if(precSpec) { + displayCharacter('.', &chars); + __int_str(decPlaces, intStrBuffer, 10, false, false, 0, false, false); + intStrBuffer[precSpec] = 0; + displayString(intStrBuffer, &chars); + } else if (altForm) { + displayCharacter('.', &chars); + } + break; + } + + case 'a': + case 'A': + // TODO: Hexadecimal floating points + break; + + default: + break; + } + + if (specifier == 'e') { + displayString("e+", &chars); + } else if (specifier == 'E') { + displayString("E+", &chars); + } + + if (specifier == 'e' || specifier == 'E') { + __int_str(expo, intStrBuffer, 10, false, false, 2, false, true); + displayString(intStrBuffer, &chars); + } + } else { + displayCharacter(format[i], &chars); + } + } + + return chars; +} diff --git a/libc/string/stpcpy.c b/libc/string/stpcpy.c new file mode 100644 index 0000000..a5d1321 --- /dev/null +++ b/libc/string/stpcpy.c @@ -0,0 +1,13 @@ +#include +#include +#include + +#define ALIGN (sizeof(size_t)) +#define ONES ((size_t)-1/UCHAR_MAX) +#define HIGHS (ONES * (UCHAR_MAX/2+1)) +#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS) + +char* __stpcpy(char* restrict d, const char* restrict s){ + for(;(*d=*s); s++, d++); + return d; +} diff --git a/libc/string/strcat.c b/libc/string/strcat.c new file mode 100644 index 0000000..79a5925 --- /dev/null +++ b/libc/string/strcat.c @@ -0,0 +1,6 @@ +#include + +char* strcat(char* restrict dest, const char* restrict src) { + strcpy(dest + strlen(dest), src); + return dest; +} diff --git a/libc/string/strcpy.c b/libc/string/strcpy.c new file mode 100644 index 0000000..52695df --- /dev/null +++ b/libc/string/strcpy.c @@ -0,0 +1,6 @@ +#include + +char* strcpy(char* restrict dest, const char* restrict src) { + __stpcpy(dest, src); + return dest; +}