diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a9ef9e..f827595 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.15) project( c-libs DESCRIPTION "C Libraries for recreational Programming." - LANGUAGES C) + LANGUAGES C ASM) add_library(c-libs ${CMAKE_CURRENT_SOURCE_DIR}/src/dyn-arr.c ${CMAKE_CURRENT_SOURCE_DIR}/src/string-view.c) @@ -17,6 +17,22 @@ target_link_libraries(strings PRIVATE c-libs) add_executable(rc ${CMAKE_CURRENT_SOURCE_DIR}/app/rc.c) target_link_libraries(rc PRIVATE c-libs) +add_executable(nolibc ${CMAKE_CURRENT_SOURCE_DIR}/app/nolibc.c + ${CMAKE_CURRENT_SOURCE_DIR}/app/entry.s) +target_compile_options( + nolibc PRIVATE -fno-asynchronous-unwind-tables -fno-unwind-tables + -fno-stack-protector -ffunction-sections -fdata-sections) +target_link_options( + nolibc + PRIVATE + -nostdlib + -static + -T + ${CMAKE_CURRENT_SOURCE_DIR}/app/nolibc.ld + -Wl,--strip-all + -Wl,--no-dynamic-linker + -Wl,--gc-sections) + include(CTest) if(BUILD_TESTING) find_package(PkgConfig REQUIRED) diff --git a/app/entry.s b/app/entry.s new file mode 100644 index 0000000..ed1e48a --- /dev/null +++ b/app/entry.s @@ -0,0 +1,29 @@ +.global _start, syscall5 + + +_start: + /* Load argc -> rdi, argv[0] -> rsi */ + xor %rbp, %rbp + pop %rdi + mov %rsp, %rsi + + and $0xFFFFFFFFFFFFFFF0, %rsp + + call main + + /* Exit with ret val of main */ + mov %rax, %rdi + mov $0x3C, %rax + syscall + +syscall5: + mov %rdi, %rax /* %rax (syscall number) = func param 1 (%rdi) */ + mov %rsi, %rdi /* %rdi (syscall param 1) = func param 2 (%rsi) */ + mov %rdx, %rsi /* %rsi (syscall param 2) = func param 3 (%rdx) */ + mov %rcx, %rdx /* %rdx (syscall param 3) = func param 4 (%rcx) */ + mov %r8, %r10 /* %r10 (syscall param 4) = func param 5 (%r8) */ + mov %r9, %r8 /* %r8 (syscall param 5) = func param 6 (%r9) */ + syscall /* Enter a syscall (return value in %rax) */ + ret /* Return value is already in %rax, we can return. */ + +.section .note.GNU-stack,"",@progbits diff --git a/app/nolibc.c b/app/nolibc.c new file mode 100644 index 0000000..3636b91 --- /dev/null +++ b/app/nolibc.c @@ -0,0 +1,18 @@ +void *syscall5(void *number, void *arg1, void *arg2, void *arg3, void *arg4, + void *arg5); + +typedef unsigned long int size_t; +typedef long int ssize_t; + +static ssize_t write(int fd, void const *data, size_t nbytes) { + return (ssize_t)syscall5((void *)1, /* SYS_write, call number 1 */ + (void *)(size_t)fd, (void *)data, (void *)nbytes, + 0, /* Ignored */ + 0 /* Ignored */ + ); +} + +int main() { + write(0, "Hello World!\n", 13); + return 0; +} diff --git a/app/nolibc.ld b/app/nolibc.ld new file mode 100644 index 0000000..6e0fe46 --- /dev/null +++ b/app/nolibc.ld @@ -0,0 +1,38 @@ +ENTRY(_start) + +PHDRS +{ + text PT_LOAD FLAGS(5); /* R + X */ + data PT_LOAD FLAGS(6); /* R + W */ +} + +SECTIONS +{ + . = 0x400000; + + .text : ALIGN(16) { + *(.text .text.*) + }:text + + .rodata : { + *(.rodata .rodata.*) + }:text + + .data : { + *(.data .data.*) + }:data + + .bss : { + *(.bss .bss.*) + *(COMMON) + }:data + + /DISCARD/ : { + *(.note*) + *(.comment*) + *(.eh_frame*) + *(.symtab*) + *(.strtab*) + } +} + diff --git a/flake.nix b/flake.nix index 3a121a4..4bee714 100644 --- a/flake.nix +++ b/flake.nix @@ -42,6 +42,7 @@ devShells.default = pkgs.mkShell { packages = [ + pkgs.asm-lsp pkgs.cmake-language-server pkgs.cmake-format pkgs.clang-tools