diff --git a/.gitignore b/.gitignore index b8172a1c..bd68726a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ toolchain/ build/ initrd/boot/moon env-local.sh -initrd/bin/** \ No newline at end of file +initrd/bin/** +base/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 037a08ce..691b5745 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,9 +5,10 @@ set(CMAKE_CXX_COMPILER_WORKS 1) set(CMAKE_CROSSCOMPILING true) -project(Luna LANGUAGES C CXX ASM_NASM VERSION 0.1.0) +project(Luna LANGUAGES C CXX ASM ASM_NASM VERSION 0.1.0) set(LUNA_ROOT ${CMAKE_CURRENT_LIST_DIR}) +set(LUNA_BASE ${CMAKE_CURRENT_LIST_DIR}/base) set(ARCH $ENV{ARCH}) @@ -17,6 +18,7 @@ endif() set(CMAKE_C_COMPILER ${ARCH}-luna-gcc) set(CMAKE_CXX_COMPILER ${ARCH}-luna-g++) +set(CMAKE_ASM_COMPILER ${ARCH}-luna-gcc) set(CMAKE_ASM_NASM_OBJECT_FORMAT elf64) @@ -27,5 +29,6 @@ set(CMAKE_FIND_ROOT_PATH ${LUNA_ROOT}/toolchain/x86-64-luna) message(STATUS "Configuring Luna for ${ARCH}") add_subdirectory(luna) +add_subdirectory(libc) add_subdirectory(kernel) -add_subdirectory(apps) \ No newline at end of file +add_subdirectory(apps) diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index cc7a0218..4c4a143a 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -1,6 +1,7 @@ function(luna_app SOURCE_FILE APP_NAME) add_executable(${APP_NAME} ${SOURCE_FILE}) - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${APP_NAME}" DESTINATION ${LUNA_ROOT}/initrd/bin) + add_dependencies(${APP_NAME} libc) + install(TARGETS ${APP_NAME} DESTINATION ${LUNA_ROOT}/initrd/bin) endfunction() -luna_app(app.asm app) \ No newline at end of file +luna_app(app.c app) diff --git a/apps/app.asm b/apps/app.asm deleted file mode 100644 index a0dffce7..00000000 --- a/apps/app.asm +++ /dev/null @@ -1,17 +0,0 @@ -section .text -global _start -_start: - mov rax, 1 - mov rdi, message - int 42h - mov rax, 1 - mov rdi, message2 - int 42h - mov rax, 0 - int 42h - -section .rodata -message: - db "Hello!", 0xa, 0 -message2: - db "I am an app", 0xa, 0 diff --git a/apps/app.c b/apps/app.c new file mode 100644 index 00000000..4f1419f1 --- /dev/null +++ b/apps/app.c @@ -0,0 +1,9 @@ +#include +#include + +int main() +{ + for (int i = 0; i < strtol("010", NULL, 0); i++) { console_print("."); } + + console_print("\n"); +} diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt new file mode 100644 index 00000000..3ac4b29d --- /dev/null +++ b/libc/CMakeLists.txt @@ -0,0 +1,61 @@ +file(GLOB HEADERS include/*.h) + +set(SOURCES + ${HEADERS} + src/stdio.cpp + src/stdlib.cpp + src/unistd.cpp +) + +if(${ARCH} STREQUAL "x86_64") + set(SOURCES + ${SOURCES} + src/arch/x86_64/syscall.S + ) +endif() + +add_library(crt0 STATIC src/arch/${ARCH}/crt0.S) +add_custom_command( + TARGET crt0 + COMMAND "${CMAKE_COMMAND}" -E copy $ ${LUNA_BASE}/usr/lib/crt0.o +) + +add_library(crti STATIC src/arch/${ARCH}/crti.S) +add_custom_command( + TARGET crti + COMMAND "${CMAKE_COMMAND}" -E copy $ ${LUNA_BASE}/usr/lib/crti.o +) + +add_library(crtn STATIC src/arch/${ARCH}/crtn.S) +add_custom_command( + TARGET crt0 + COMMAND "${CMAKE_COMMAND}" -E copy $ ${LUNA_BASE}/usr/lib/crtn.o +) + +add_library(bare_libc STATIC ${SOURCES}) + +target_link_libraries(bare_libc PUBLIC luna) + +target_include_directories(bare_libc PUBLIC include/) + +target_compile_options(bare_libc PRIVATE -Wall -Wextra -Werror -pedantic -nostdlib) + +target_link_options(bare_libc PRIVATE -nostdlib) + +set_target_properties(bare_libc PROPERTIES CXX_STANDARD 20) + +add_custom_target(libc + COMMAND ${CMAKE_AR} -x $ + COMMAND ${CMAKE_AR} -x $ + COMMAND ${CMAKE_AR} -rcs ${CMAKE_CURRENT_BINARY_DIR}/libc.a *.o + COMMAND rm *.o + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS bare_libc luna +) + +add_custom_command( + TARGET libc + COMMAND "${CMAKE_COMMAND}" -E copy ${CMAKE_CURRENT_BINARY_DIR}/libc.a ${LUNA_BASE}/usr/lib/libc.a +) + +file(WRITE "${LUNA_BASE}/usr/lib/libm.a" "INPUT(libc.a)") diff --git a/libc/include/bits/attrs.h b/libc/include/bits/attrs.h new file mode 100644 index 00000000..f71081cc --- /dev/null +++ b/libc/include/bits/attrs.h @@ -0,0 +1,10 @@ +#ifndef _BITS_ATTRS_H +#define _BITS_ATTRS_H + +#if !defined(_STDLIB_H) +#error "Never include bits/attrs.h directly; use one of the standard library headers." +#endif + +#define __noreturn __attribute__((noreturn)) + +#endif diff --git a/libc/include/stdio.h b/libc/include/stdio.h new file mode 100644 index 00000000..746fe3a9 --- /dev/null +++ b/libc/include/stdio.h @@ -0,0 +1,15 @@ +#ifndef _STDIO_H +#define _STDIO_H + +#ifdef __cplusplus +extern "C" +{ +#endif + + void console_print(const char*); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h new file mode 100644 index 00000000..7e6a0f56 --- /dev/null +++ b/libc/include/stdlib.h @@ -0,0 +1,73 @@ +#ifndef _STDLIB_H +#define _STDLIB_H + +#include +#include + +typedef struct +{ + int quot; + int rem; +} div_t; + +typedef struct +{ + long quot; + long rem; +} ldiv_t; + +typedef struct +{ + long long quot; + long long rem; +} lldiv_t; + +#ifdef __cplusplus +extern "C" +{ +#endif + + int abs(int); + long labs(long); + long long llabs(long long); + + div_t div(int, int); + ldiv_t ldiv(long, long); + lldiv_t lldiv(long long, long long); + + void* malloc(size_t); + void* calloc(size_t, size_t); + void* realloc(void*, size_t); + void free(void*); + + __noreturn void abort(); + int atexit(void (*)(void)); + + int atoi(const char*); + long atol(const char*); + long long atoll(const char*); + + double atof(const char*); + + double strtod(const char*, char**); + + long strtol(const char*, char**, int); + unsigned long strtoul(const char*, char**, int); + + int rand(); + void srand(int); + + __noreturn void exit(int); + + int system(const char*); + + char* getenv(const char*); + + void qsort(void*, size_t, size_t, int (*)(const void*, const void*)); + void* bsearch(const void*, const void*, size_t, size_t, int (*)(const void*, const void*)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libc/include/sys/syscall.h b/libc/include/sys/syscall.h new file mode 100644 index 00000000..b7e75c17 --- /dev/null +++ b/libc/include/sys/syscall.h @@ -0,0 +1,6 @@ +#ifndef _SYS_SYSCALL_H +#define _SYS_SYSCALL_H + +#include + +#endif diff --git a/libc/include/sys/types.h b/libc/include/sys/types.h new file mode 100644 index 00000000..25b16927 --- /dev/null +++ b/libc/include/sys/types.h @@ -0,0 +1,9 @@ +#ifndef _SYS_TYPES_H +#define _SYS_TYPES_H + +#define __need_size_t +#include + +typedef int pid_t; + +#endif diff --git a/libc/include/unistd.h b/libc/include/unistd.h new file mode 100644 index 00000000..6ad244fa --- /dev/null +++ b/libc/include/unistd.h @@ -0,0 +1,15 @@ +#ifndef _UNISTD_H +#define _UNISTD_H + +#ifdef __cplusplus +extern "C" +{ +#endif + + long syscall(long, ...); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libc/src/arch/x86_64/crt0.S b/libc/src/arch/x86_64/crt0.S new file mode 100644 index 00000000..cfebdc21 --- /dev/null +++ b/libc/src/arch/x86_64/crt0.S @@ -0,0 +1,20 @@ +.section .text + +.global _start +.extern exit +_start: + # Set up end of the stack frame linked list. + movq $0, %rbp + pushq %rbp # rip=0 + pushq %rbp # rbp=0 + movq %rsp, %rbp + + # Run the global constructors. + call _init + + # Run main + call main + + # Terminate the process with the exit code. + movl %eax, %edi + call exit diff --git a/libc/src/arch/x86_64/crti.S b/libc/src/arch/x86_64/crti.S new file mode 100644 index 00000000..03ad2f91 --- /dev/null +++ b/libc/src/arch/x86_64/crti.S @@ -0,0 +1,13 @@ +.section .init +.global _init +_init: + push %rbp + movq %rsp, %rbp + /* gcc will nicely put the contents of crtbegin.o's .init section here. */ + +.section .fini +.global _fini +_fini: + push %rbp + movq %rsp, %rbp + /* gcc will nicely put the contents of crtbegin.o's .fini section here. */ diff --git a/libc/src/arch/x86_64/crtn.S b/libc/src/arch/x86_64/crtn.S new file mode 100644 index 00000000..762c7f6c --- /dev/null +++ b/libc/src/arch/x86_64/crtn.S @@ -0,0 +1,9 @@ +.section .init + /* gcc will nicely put the contents of crtend.o's .init section here. */ + popq %rbp + ret + +.section .fini + /* gcc will nicely put the contents of crtend.o's .fini section here. */ + popq %rbp + ret diff --git a/libc/src/arch/x86_64/syscall.S b/libc/src/arch/x86_64/syscall.S new file mode 100644 index 00000000..9ec1286c --- /dev/null +++ b/libc/src/arch/x86_64/syscall.S @@ -0,0 +1,10 @@ +.global arch_invoke_syscall +arch_invoke_syscall: + mov %rdi, %rax + mov %rsi, %rdi + mov %rdx, %rsi + mov %rcx, %rdx + mov %r8, %r10 + mov %r9, %r8 + int $66 + ret diff --git a/libc/src/stdio.cpp b/libc/src/stdio.cpp new file mode 100644 index 00000000..aec92562 --- /dev/null +++ b/libc/src/stdio.cpp @@ -0,0 +1,11 @@ +#include +#include +#include + +extern "C" +{ + void console_print(const char* str) + { + syscall(SYS_console_print, str); + } +} diff --git a/libc/src/stdlib.cpp b/libc/src/stdlib.cpp new file mode 100644 index 00000000..87fb244d --- /dev/null +++ b/libc/src/stdlib.cpp @@ -0,0 +1,30 @@ +#include +#include +#include +#include + +extern "C" +{ + // FIXME: Check for overflow in both strtol() and strtoul(). + long strtol(const char* str, char** endptr, int base) + { + return (long)parse_signed_integer(str, const_cast(endptr), base); + } + + unsigned long strtoul(const char* str, char** endptr, int base) + { + return (unsigned long)parse_unsigned_integer(str, const_cast(endptr), base); + } + + __noreturn void abort() + { + syscall(SYS_exit); + __builtin_unreachable(); + } + + __noreturn void exit(int) + { + syscall(SYS_exit); + __builtin_unreachable(); + } +} diff --git a/libc/src/unistd.cpp b/libc/src/unistd.cpp new file mode 100644 index 00000000..58b0c277 --- /dev/null +++ b/libc/src/unistd.cpp @@ -0,0 +1,26 @@ +#include +#include +#include + +extern "C" long arch_invoke_syscall(long, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); + +extern "C" +{ + long syscall(long num, ...) + { + va_list ap; + va_start(ap, num); + + uintptr_t arg0 = va_arg(ap, uintptr_t); + uintptr_t arg1 = va_arg(ap, uintptr_t); + uintptr_t arg2 = va_arg(ap, uintptr_t); + uintptr_t arg3 = va_arg(ap, uintptr_t); + uintptr_t arg4 = va_arg(ap, uintptr_t); + + long rc = arch_invoke_syscall(num, arg0, arg1, arg2, arg3, arg4); + + va_end(ap); + + return rc; + } +} diff --git a/luna/CMakeLists.txt b/luna/CMakeLists.txt index 4d8be399..90dd5a40 100644 --- a/luna/CMakeLists.txt +++ b/luna/CMakeLists.txt @@ -36,24 +36,23 @@ target_compile_options(luna-freestanding PRIVATE -nostdlib -mcmodel=kernel) target_include_directories(luna-freestanding PUBLIC include/) set_target_properties(luna-freestanding PROPERTIES CXX_STANDARD 20) -#add_library(luna ${SOURCES}) -#target_compile_options(luna PRIVATE -Wall -Wextra -Werror -Wvla) -#target_compile_options(luna PRIVATE -Wdisabled-optimization -Wformat=2 -Winit-self) -#target_compile_options(luna PRIVATE -Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef) -#target_compile_options(luna PRIVATE -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion) -#target_compile_options(luna PRIVATE -fno-asynchronous-unwind-tables -fno-omit-frame-pointer) -#target_include_directories(luna PUBLIC include/) -#set_target_properties(luna PROPERTIES CXX_STANDARD 20) +add_library(luna ${SOURCES}) +target_compile_options(luna PRIVATE -Wall -Wextra -Werror -Wvla) +target_compile_options(luna PRIVATE -Wdisabled-optimization -Wformat=2 -Winit-self) +target_compile_options(luna PRIVATE -Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef) +target_compile_options(luna PRIVATE -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion) +target_compile_options(luna PRIVATE -fno-asynchronous-unwind-tables -fno-omit-frame-pointer -std=c++20) +target_include_directories(luna PUBLIC include/) if("${ARCH}" MATCHES "x86_64") target_compile_options(luna-freestanding PRIVATE -mno-red-zone) target_compile_options(luna-freestanding PRIVATE -mno-80387 -mno-mmx -mno-sse -mno-sse2) target_compile_definitions(luna-freestanding PUBLIC ARCH_X86_64) -#target_compile_definitions(luna PUBLIC ARCH_X86_64) +target_compile_definitions(luna PUBLIC ARCH_X86_64) endif() if(LUNA_DEBUG_SYMBOLS) message(STATUS "Building Luna with debug symbols") - #target_compile_options(luna PRIVATE -ggdb) + target_compile_options(luna PRIVATE -ggdb) target_compile_options(luna-freestanding PRIVATE -ggdb) -endif() \ No newline at end of file +endif() diff --git a/tools/install-headers.sh b/tools/install-headers.sh index 94cf0b7c..c851192f 100755 --- a/tools/install-headers.sh +++ b/tools/install-headers.sh @@ -7,8 +7,7 @@ cd $LUNA_ROOT mkdir -p $LUNA_BASE mkdir -p $LUNA_BASE/usr/include -mkdir -p $LUNA_BASE/usr/include/moon mkdir -p $LUNA_BASE/usr/include/luna -cp -RT kernel/**/*.h $LUNA_BASE/usr/include/moon -cp -RT luna/include/luna/*.h $LUNA_BASE/usr/include/luna \ No newline at end of file +cp -RT libc/include/ $LUNA_BASE/usr/include +cp -RT luna/include/luna/ $LUNA_BASE/usr/include/luna