refactor(userspace): build using cmake

Signed-off-by: EnderIce2 <enderice2@protonmail.com>
This commit is contained in:
2025-03-15 23:05:17 +00:00
parent 40f46312f8
commit 201ace7eec
73 changed files with 2819 additions and 2255 deletions

View File

@ -0,0 +1,21 @@
file(GLOB_RECURSE SYSDEPS_SOURCES ${SYSDEPS_PATH}/*.c ${SYSDEPS_GENERIC}/*.c)
file(GLOB_RECURSE INTERPRETER_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.c")
list(APPEND INTERPRETER_FILES ${SYSDEPS_SOURCES})
add_executable(ld.so ${INTERPRETER_FILES})
execute_process(COMMAND git rev-parse HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMIT
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(GIT_COMMIT)
add_compile_definitions(LIBC_GIT_COMMIT="${GIT_COMMIT}")
endif()
add_compile_definitions(FENNIX_DYNAMIC_LOADER="1")
install(TARGETS ld.so DESTINATION lib)
target_compile_options(ld.so PRIVATE -fvisibility=hidden -fPIC)
target_link_options(ld.so PRIVATE -nostdlib -shared -fPIC -fPIE -fno-plt -Wl,-e,_dl_start)

View File

@ -1,40 +0,0 @@
default:
$(error Do not run this Makefile directly!)
OBJECT_NAME := ld.so
OUTPUT_DIR=$(WORKSPACE_DIR)/out/lib/
SYSROOT = --sysroot=$(WORKSPACE_DIR)/out/
S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c')
CXX_SOURCES = $(shell find ./ -type f -name '*.cpp')
OBJ = ${S_SOURCES:.S=.o} ${C_SOURCES:.c=.o} ${CXX_SOURCES:.cpp=.o}
CFLAGS := -fvisibility=hidden -fPIC -I$(WORKSPACE_DIR)/out/include -DLIBC_GIT_COMMIT='"$(shell git rev-parse HEAD)"'
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always
endif
build: $(OBJECT_NAME)
$(OBJECT_NAME): $(OBJ)
$(info Linking $@)
$(CC) -nostdlib -shared -fPIC -fPIE -fno-plt -Wl,-soname,$(OBJECT_NAME) $(SYSROOT) $(OBJ) -o $(OBJECT_NAME)
cp $(OBJECT_NAME) $(OUTPUT_DIR)$(OBJECT_NAME)
%.o: %.c
$(info Compiling $<)
$(CC) $(CFLAGS) -std=c17 -c $< -o $@
%.o: %.cpp
$(info Compiling $<)
$(CC) $(CFLAGS) -std=c++20 -c $< -o $@
%.o: %.S
$(info Compiling $<)
$(AS) -c $< -o $@
clean:
rm -f $(OBJ) $(OBJECT_NAME)

View File

@ -15,8 +15,9 @@
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <fennix/syscalls.h>
#include <bits/libc.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <stdint.h>
#include <stddef.h>
#include <errno.h>
@ -39,7 +40,7 @@ MemoryBlock *memory_pool = NULL;
void *request_page(size_t size)
{
size_t aligned_size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
void *addr = (void *)call_mmap(NULL, aligned_size, __SYS_PROT_READ | __SYS_PROT_WRITE, __SYS_MAP_ANONYMOUS | __SYS_MAP_PRIVATE, -1, 0);
void *addr = (void *)sysdep(MemoryMap)(NULL, aligned_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if ((intptr_t)addr < 0)
return NULL;
return addr;
@ -48,7 +49,7 @@ void *request_page(size_t size)
void free_page(void *addr, size_t size)
{
size_t aligned_size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
call_munmap(addr, aligned_size);
sysdep(MemoryUnmap)(addr, aligned_size);
}
MemoryBlock *allocate_block(size_t slot_size)

View File

@ -15,7 +15,7 @@
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <fennix/syscalls.h>
#include <bits/libc.h>
#include <sys/types.h>
#include <stdint.h>
#include <stddef.h>

View File

@ -15,11 +15,14 @@
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <fennix/syscalls.h>
#include <bits/libc.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <inttypes.h>
#include <stddef.h>
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include "elf.h"
@ -167,9 +170,15 @@ __attribute__((noinline)) void *_dl_fixup(ElfInfo *Info, long RelIndex)
return ret;
}
#ifdef __fennix__
#include <fennix/syscalls.h>
#endif
int _dl_preload()
{
#ifdef __fennix__
call_api_version(0);
#endif
/* TODO: Do aditional checks for miscellaneous things */
@ -353,16 +362,16 @@ void ProcessNeededLibraries(Elf_Dyn *elem, ElfInfo *Info)
strcpy(fullLibPath, "/lib/");
strcat(fullLibPath, libPath);
/* TODO: more checks and also check environment variables */
if (call_access(fullLibPath, __SYS_F_OK) != 0)
if (sysdep(Access)(fullLibPath, F_OK) != 0)
{
printf("dl: Can't access %s\n", fullLibPath);
return;
}
int fd = call_open(fullLibPath, __SYS_O_RDONLY, 0644);
int fd = sysdep(Open)(fullLibPath, O_RDONLY, 0644);
int status = LoadElf(fd, fullLibPath, &info);
elem->d_un.d_ptr = (uintptr_t)info; /* if LoadElf fails, info will still be NULL */
call_close(fd);
sysdep(Close)(fd);
if (status < 0) /* announce that LoadElf failed */
printf("dl: Can't load %s\n", fullLibPath);
}
@ -431,7 +440,7 @@ int LoadElfPhdrDYN(int fd, ElfInfo *Info)
for (Elf_Half i = 0; i < header.e_phnum; i++)
{
ssize_t read = call_pread(fd, &phdr, sizeof(Elf_Phdr), header.e_phoff + (header.e_phentsize * i));
ssize_t read = sysdep(PRead)(fd, &phdr, sizeof(Elf_Phdr), header.e_phoff + (header.e_phentsize * i));
if (read != sizeof(Elf_Phdr))
{
printf("dl: Can't read program header %d\n", i);
@ -450,23 +459,23 @@ int LoadElfPhdrDYN(int fd, ElfInfo *Info)
int mmapProt = 0;
if (phdr.p_flags & PF_X)
mmapProt |= __SYS_PROT_EXEC;
mmapProt |= PROT_EXEC;
if (phdr.p_flags & PF_W)
mmapProt |= __SYS_PROT_WRITE;
mmapProt |= PROT_WRITE;
if (phdr.p_flags & PF_R)
mmapProt |= __SYS_PROT_READ;
mmapProt |= PROT_READ;
off_t sectionOffset = ALIGN_DOWN(phdr.p_vaddr, phdr.p_align);
size_t sectionSize = ALIGN_UP(phdr.p_memsz + (phdr.p_vaddr - sectionOffset), phdr.p_align);
uintptr_t section = call_mmap(base + sectionOffset,
sectionSize, mmapProt,
__SYS_MAP_ANONYMOUS | __SYS_MAP_PRIVATE | __SYS_MAP_FIXED,
-1, 0);
uintptr_t section = (uintptr_t)sysdep(MemoryMap)((void *)(base + sectionOffset),
sectionSize, mmapProt,
MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED,
-1, 0);
sectionOffset = phdr.p_vaddr - ALIGN_DOWN(phdr.p_vaddr, phdr.p_align);
if (phdr.p_filesz > 0)
{
ssize_t read = call_pread(fd, section + sectionOffset, phdr.p_filesz, phdr.p_offset);
ssize_t read = sysdep(PRead)(fd, (void *)(section + sectionOffset), phdr.p_filesz, phdr.p_offset);
if (read != phdr.p_filesz)
{
printf("dl: Can't read segment %d in PT_LOAD\n", i);
@ -495,15 +504,15 @@ int LoadElfPhdrDYN(int fd, ElfInfo *Info)
{
int mmapProt = 0;
if (phdr.p_flags & PF_X)
mmapProt |= __SYS_PROT_EXEC;
mmapProt |= PROT_EXEC;
if (phdr.p_flags & PF_W)
mmapProt |= __SYS_PROT_WRITE;
mmapProt |= PROT_WRITE;
if (phdr.p_flags & PF_R)
mmapProt |= __SYS_PROT_READ;
mmapProt |= PROT_READ;
dynamicTable = (Elf_Dyn *)call_mmap(0, ALIGN_UP(phdr.p_memsz, phdr.p_align),
mmapProt, __SYS_MAP_ANONYMOUS | __SYS_MAP_PRIVATE | __SYS_MAP_FIXED,
-1, 0);
dynamicTable = (Elf_Dyn *)sysdep(MemoryMap)(0, ALIGN_UP(phdr.p_memsz, phdr.p_align),
mmapProt, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED,
-1, 0);
if ((intptr_t)dynamicTable <= 0)
{
@ -511,7 +520,7 @@ int LoadElfPhdrDYN(int fd, ElfInfo *Info)
return (int)(uintptr_t)dynamicTable;
}
read = call_pread(fd, dynamicTable, phdr.p_memsz, phdr.p_offset);
read = sysdep(PRead)(fd, dynamicTable, phdr.p_memsz, phdr.p_offset);
if (read != phdr.p_memsz)
{
printf("dl: Can't read PT_DYNAMIC\n");
@ -598,7 +607,7 @@ int LoadElf(int fd, char *Path, ElfInfo **Out)
}
Elf_Ehdr header;
call_pread(fd, &header, sizeof(Elf_Ehdr), 0);
sysdep(PRead)(fd, &header, sizeof(Elf_Ehdr), 0);
int status = CheckElfEhdr(&header, Path);
if (status != 0)
@ -606,11 +615,11 @@ int LoadElf(int fd, char *Path, ElfInfo **Out)
info = AllocateLib();
info->Header = header;
info->Path = (char *)call_mmap(0,
ALIGN_UP(strlen(Path) + 1, 0x1000 /* TODO: get page size from kernel */),
__SYS_PROT_READ,
__SYS_MAP_ANONYMOUS | __SYS_MAP_PRIVATE,
-1, 0);
info->Path = (char *)sysdep(MemoryMap)(0,
ALIGN_UP(strlen(Path) + 1, 0x1000 /* TODO: get page size from kernel */),
PROT_READ,
MAP_ANONYMOUS | MAP_PRIVATE,
-1, 0);
if ((intptr_t)info->Path <= 0)
{
printf("dl: Can't allocate memory for path\n");
@ -648,7 +657,7 @@ int LoadElf(int fd, char *Path, ElfInfo **Out)
if (status < 0)
{
call_munmap((uintptr_t)info->Path, ALIGN_UP(strlen(Path) + 1, 0x1000));
sysdep(MemoryUnmap)((void *)info->Path, ALIGN_UP(strlen(Path) + 1, 0x1000));
FreeLib(info);
return status;
}
@ -956,18 +965,18 @@ int _dl_main(int argc, char *argv[], char *envp[])
{
char *path = argv[0];
ElfInfo *info = NULL;
if (call_access(path, __SYS_F_OK) < 0)
if (sysdep(Access)(path, F_OK) < 0)
{
printf("dl: Can't access file %s\n", path);
return -EACCES;
}
int fd = call_open(path, __SYS_O_RDONLY, 0644);
int fd = sysdep(Open)(path, O_RDONLY, 0644);
int status = LoadElf(fd, path, &info);
if (status < 0)
{
printf("%s: Can't load ELF file\n", path);
call_close(fd);
sysdep(Close)(fd);
return status;
}
@ -975,11 +984,11 @@ int _dl_main(int argc, char *argv[], char *envp[])
if (status < 0)
{
printf("%s: Can't relocate ELF file\n", path);
call_close(fd);
sysdep(Close)(fd);
return status;
}
call_close(fd);
sysdep(Close)(fd);
Elf_Addr entry = info->BaseAddress + info->Header.e_entry;
return ((int (*)(int, char *[], char *[]))entry)(argc, argv, envp);
}

View File

@ -1,4 +1,4 @@
/* nanoprintf v0.5.3: a tiny embeddable printf replacement written in C.
/* nanoprintf v0.5.4: a tiny embeddable printf replacement written in C.
https://github.com/charlesnicholson/nanoprintf
charles.nicholson+nanoprintf@gmail.com
dual-licensed under 0bsd and unlicense, take your pick. see eof for details. */
@ -336,6 +336,7 @@ static int npf_parse_format_spec(char const *format, npf_format_spec_t *out_spec
}
#if NANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS == 1
out_spec->field_width = 0;
out_spec->field_width_opt = NPF_FMT_SPEC_OPT_NONE;
if (*cur == '*')
{
@ -344,7 +345,6 @@ static int npf_parse_format_spec(char const *format, npf_format_spec_t *out_spec
}
else
{
out_spec->field_width = 0;
while ((*cur >= '0') && (*cur <= '9'))
{
out_spec->field_width_opt = NPF_FMT_SPEC_OPT_LITERAL;

View File

@ -17,7 +17,8 @@
#include <stddef.h>
#include <stdarg.h>
#include <fennix/syscalls.h>
#include <bits/libc.h>
#include <sys/mman.h>
#include "elf.h"
#include "misc.h"
@ -31,7 +32,7 @@ void flush_buffer()
{
if (print_buffer_offset > 0)
{
call_write(1, print_buffer, print_buffer_offset);
sysdep(Write)(1, print_buffer, print_buffer_offset);
print_buffer_offset = 0;
}
}
@ -45,11 +46,11 @@ void print_wrapper(int c, void *)
void __init_print_buffer()
{
print_buffer = (char *)call_mmap(0,
0x1000,
__SYS_PROT_READ | __SYS_PROT_WRITE,
__SYS_MAP_PRIVATE | __SYS_MAP_ANONYMOUS,
-1, 0);
print_buffer = (char *)sysdep(MemoryMap)(0,
0x1000,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0);
print_buffer_size = 0x1000;
print_buffer_offset = 0;
}
@ -58,7 +59,7 @@ void __fini_print_buffer()
{
flush_buffer();
if (print_buffer != NULL)
call_munmap(print_buffer, 0x1000);
sysdep(MemoryUnmap)(print_buffer, 0x1000);
print_buffer = NULL;
}

View File

@ -15,7 +15,7 @@
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <fennix/syscalls.h>
#include <bits/libc.h>
// const char __interp[] __attribute__((section(".interp"))) = "/boot/fennix.elf";
@ -97,54 +97,11 @@ const struct
void __init_print_buffer();
void __fini_print_buffer();
__attribute__((naked, used, no_stack_protector)) void _start()
{
#if defined(__amd64__)
__asm__(
"xorq %rbp, %rbp\n" /* Clear rbp */
"push %rdi\n"
"push %rsi\n"
"push %rdx\n"
"push %rcx\n"
"push %r8\n"
"push %r9\n"
"call __init_print_buffer\n" /* Call __init_print_buffer */
"call _dl_preload\n" /* Call _dl_preload */
"movl %eax, %edi\n" /* Move return value to edi */
"cmp $0, %edi\n" /* Check if return value is 0 */
"jne _exit\n" /* If not, jump to _exit */
"pop %r9\n"
"pop %r8\n"
"pop %rcx\n"
"pop %rdx\n"
"pop %rsi\n"
"pop %rdi\n"
"call main\n" /* Call _dl_main */
"movl %eax, %edi\n" /* Move return value to edi */
"call _exit\n"); /* Call _exit */
#elif defined(__i386__)
#warning "i386 _start not implemented"
#elif defined(__arm__)
#warning "arm _start not implemented"
#elif defined(__aarch64__)
#warning "aarch64 _start not implemented"
#else
#error "Unsupported architecture"
#endif
}
__attribute__((no_stack_protector)) _Noreturn void _exit(int status)
{
__fini_print_buffer();
call_exit(status);
/* At this point, the program *SHOULD* have exited. */
#if defined(__amd64__) || defined(__i386__)
__asm__("ud2\n");
#endif
sysdep(Exit)(status);
/* At this point, the program *SHOULD* have exited. */
__builtin_unreachable();
}