Add ET_DYN support for the ELF loader, which required adding

relocations, add some more functions to libxunil, use include inside of
tests instead of manually defining types and add basic libc header
files. Move libxunil to the user folder, and add helloworld and
doomgeneric as apps
This commit is contained in:
csd4ni3l
2026-04-01 21:25:34 +02:00
parent 47a480009f
commit 6ac13a876f
23 changed files with 437 additions and 37 deletions

View File

@@ -0,0 +1,4 @@
gcc -nostdlib -nostdinc -static -static-pie \
-o $1 $1.c \
-L../../libxunil/target/release -l:libxunil.a
mv $1 ../../../assets/$1.elf

View File

@@ -0,0 +1,6 @@
#include "../src/stdio.h"
void _start() {
write(0, "Hello, World!", 13);
exit(0);
}

1
user/libxunil/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/target

7
user/libxunil/Cargo.lock generated Normal file
View File

@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "libxunil"
version = "0.1.0"

12
user/libxunil/Cargo.toml Normal file
View File

@@ -0,0 +1,12 @@
[package]
name = "libxunil"
version = "0.1.0"
edition = "2024"
[lib]
name = "xunil"
crate-type = ["staticlib"]
[profile.release]
panic = "abort"
opt-level = "s"

View File

@@ -0,0 +1,2 @@
#include <stddef.h>
#include <stdint.h>

View File

@@ -0,0 +1,32 @@
#pragma once
#include <stddef.h>
#include <stdarg.h>
typedef struct FILE FILE;
extern FILE *stdin;
extern FILE *stdout;
extern FILE *stderr;
#define EOF (-1)
FILE *fopen(const char *path, const char *mode);
int fclose(FILE *fp);
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *fp);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *fp);
int fseek(FILE *fp, long offset, int whence);
long ftell(FILE *fp);
int fflush(FILE *fp);
char *fgets(char *s, int size, FILE *fp);
int fputs(const char *s, FILE *fp);
int feof(FILE *fp);
int ferror(FILE *fp);
int printf(const char *fmt, ...);
int fprintf(FILE *fp, const char *fmt, ...);
int sprintf(char *buf, const char *fmt, ...);
int snprintf(char *buf, size_t size, const char *fmt, ...);
int vsnprintf(char *buf, size_t size, const char *fmt, va_list ap);
int vfprintf(FILE *fp, const char *fmt, va_list ap);
void write(int fd, const char* buf, unsigned long count);
void exit(int code);

View File

@@ -0,0 +1,20 @@
#pragma once
#include <stddef.h>
void *malloc(size_t size);
void *calloc(size_t nmemb, size_t size);
void *realloc(void *ptr, size_t size);
void free(void *ptr);
void exit(int status);
void abort(void);
int atoi(const char *s);
long atol(const char *s);
double atof(const char *s);
long strtol(const char *s, char **endptr, int base);
double strtod(const char *s, char **endptr);
char *getenv(const char *name);
void qsort(void *base, size_t nmemb, size_t size, int (*cmp)(const void *, const void *));
int abs(int x);

View File

@@ -0,0 +1,22 @@
#pragma once
#include <stddef.h>
void *memset(void *s, int c, size_t n);
void *memcpy(void *dst, const void *src, size_t n);
void *memmove(void *dst, const void *src, size_t n);
int memcmp(const void *s1, const void *s2, size_t n);
void *memchr(const void *s, int c, size_t n);
size_t strlen(const char *s);
char *strcpy(char *dst, const char *src);
char *strncpy(char *dst, const char *src, size_t n);
char *strcat(char *dst, const char *src);
char *strncat(char *dst, const char *src, size_t n);
int strcmp(const char *s1, const char *s2);
int strncmp(const char *s1, const char *s2, size_t n);
char *strchr(const char *s, int c);
char *strrchr(const char *s, int c);
char *strstr(const char *haystack, const char *needle);
char *strtok(char *str, const char *delim);
char *strdup(const char *s);
char *strerror(int errnum);

View File

@@ -0,0 +1,8 @@
#pragma once
#include <stddef.h>
int strcasecmp(const char *s1, const char *s2);
int strncasecmp(const char *s1, const char *s2, size_t n);
void bzero(void *s, size_t n);
void bcopy(const void *src, void *dest, size_t n);
int bcmp(const void *s1, const void *s2, size_t n);

67
user/libxunil/src/lib.rs Normal file
View File

@@ -0,0 +1,67 @@
#![no_std]
#![no_main]
use crate::syscall::syscall3;
pub mod syscall;
const SYS_EXIT: usize = 1;
const SYS_WRITE: usize = 60;
#[unsafe(no_mangle)]
extern "C" fn write(fd: i32, buf: *const u8, count: usize) -> isize {
unsafe { syscall3(SYS_WRITE, fd as usize, buf as usize, count) }
}
#[unsafe(no_mangle)]
extern "C" fn exit(code: i32) -> ! {
unsafe { syscall3(SYS_EXIT, code as usize, 0, 0) };
loop {}
}
#[unsafe(no_mangle)]
extern "C" fn strlen(s: *const u8) -> usize {
let mut len = 0;
while unsafe { *s.add(len) } != 0 {
len += 1;
}
len
}
#[unsafe(no_mangle)]
extern "C" fn puts(s: *const u8) -> isize {
write(1, s, strlen(s));
0
}
#[unsafe(no_mangle)]
extern "C" fn abs(n: i32) -> i32 {
n.abs()
}
#[unsafe(no_mangle)]
extern "C" fn atoi(mut c: *const u8) -> i32 {
let mut value: i32 = 0;
let mut sign: i32 = 1;
unsafe {
if (*c) == b'+' || (*c) == b'-' {
if *c == b'-' {
sign = -1;
}
c = c.add(1);
}
while (*c).is_ascii_digit() {
value *= 10;
value += ((*c) - b'0') as i32;
c = c.add(1);
}
}
value * sign
}
#[panic_handler]
fn panic(_: &core::panic::PanicInfo) -> ! {
loop {}
}

View File

@@ -0,0 +1,32 @@
#[inline(always)]
pub unsafe fn syscall0(num: usize) -> isize {
let ret: isize;
unsafe {
core::arch::asm!(
"int 0x80",
in("rax") num,
lateout("rax") ret,
options(nostack)
);
}
ret
}
#[inline(always)]
pub unsafe fn syscall3(num: usize, arg0: usize, arg1: usize, arg2: usize) -> isize {
let ret: isize;
unsafe {
core::arch::asm!(
"int 0x80",
in("rax") num,
in("rdi") arg0,
in("rsi") arg1,
in("rdx") arg2,
lateout("rax") ret,
options(nostack)
);
}
ret
}

View File

@@ -0,0 +1,22 @@
abs
atoi
calloc
__ctype_toupper_loc
fprintf
free
malloc
memcpy
memset
printf
realloc
__stack_chk_fail
stderr
strcasecmp
strcmp
strdup
strlen
strncasecmp
strncmp
strncpy
strrchr
toupper