commit dbbe4055eb52d042e3f4c5befd3d4ce5d2675af4
Author: evenfri <evenfri256@gmail.com>
Date: Fri, 24 Jul 2026 01:05:53 +0800
initial commit
Diffstat:
12 files changed, 196 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1,4 @@
+o.*
+*.o
+libc.a
+test/
diff --git a/README b/README
@@ -0,0 +1,45 @@
+===============================================================================
+ README
+===============================================================================
+Minimal freestanding C library (libc) for Linux x86_64 built from scratch
+without external system dependencies.
+
+1. Description
+--------------
+This project provides a lightweight, modular C library designed for learning,
+low-level system control, and minimal binary sizes. It features a custom
+assembly entry point (_start), System V AMD64 ABI compliance, and a flat source
+tree where each function lives in its own file.
+
+2. Features
+-----------
+* Zero external C library or host header dependencies.
+* Unified header file (libc.h) containing essential types and prototypes.
+* Granular archive build (libc.a) — only referenced objects are linked.
+* Custom entry point supporting argc, argv, and envp stack extraction.
+
+3. Building
+-----------
+The project uses Plan 9 'mk' for build automation.
+
+ mk — build libc.a
+ mk clean — remove intermediate object files
+
+4. Usage Example
+----------------
+Include libc.h in your application and link against libc.a:
+
+ #include <libc.h>
+
+ int main(int argc, char *argv[], char *envp[]) {
+ char *msg = "Hello world!\n";
+ write(stdout, msg, strlen(msg));
+ return 0;
+ }
+
+Compile and link using freestanding flags:
+
+ cc -ffreestanding -nostdlib -nostdinc -I. -c main.c -o main.o
+ ld -o app main.o libc.a
+
+===============================================================================
diff --git a/_exit.c b/_exit.c
@@ -0,0 +1,17 @@
+/*
+ * _exit.c — direct exit system call
+ * Copyright (C) 2026. All rights reserved.
+ */
+
+#include "libc.h"
+
+void _exit(int status) {
+ __asm__ volatile (
+ "syscall"
+ :
+ : "a"(sys_exit), "D"(status)
+ : "memory"
+ );
+
+ for (;;) {}
+}
diff --git a/example/main.c b/example/main.c
@@ -0,0 +1,7 @@
+#include <libc.h>
+
+int main(int argc, char *argv[], char *envp[]) {
+ char *msg = "Hello world, with my libc!\n";
+ write(1, msg, strlen(msg));
+ return 0;
+}
diff --git a/example/mkfile b/example/mkfile
@@ -0,0 +1,9 @@
+<$LPLAN9/src/mkhdr
+
+ld = ld
+cflags = -nostdlib -ffreestanding -I..
+lib = ../libc.a
+ofiles = main.$o
+targ = app
+
+<$LPLAN9/src/mkone
diff --git a/exit.c b/exit.c
@@ -0,0 +1,10 @@
+/*
+ * exit.c — normal program termination
+ * Copyright (C) 2026. All rights reserved.
+ */
+
+#include "libc.h"
+
+void exit(int status) {
+ _exit(status);
+}
diff --git a/libc.h b/libc.h
@@ -0,0 +1,33 @@
+/*
+ * libc.h — core definitions and function prototypes
+ * Copyright (C) 2026. All rights reserved.
+ */
+
+#ifndef _libc_h
+#define _libc_h
+
+/* base types */
+typedef unsigned long size_t;
+typedef long ssize_t;
+
+#ifndef null
+#define null ((void*)0)
+#endif
+
+#define stdin 0
+#define stdout 1
+#define stderr 2
+
+/* syscall numbers */
+#define sys_write 1
+#define sys_exit 60
+
+/* function prototypes */
+ssize_t write(int fd, const void *buf, size_t count);
+void _exit(int status);
+void exit(int status);
+
+/* string functions prototypes */
+size_t strlen(const char* str);
+
+#endif /* _libc_h */
diff --git a/mkfile b/mkfile
@@ -0,0 +1,16 @@
+<$LPLAN9/src/mkhdr
+
+cc = ./wrapers/cc
+cflags = -I.
+ld = ld
+lib = libc.a
+
+ofiles = start.$o \
+ _exit.$o \
+ exit.$o \
+ write.$o \
+ strlen.$o \
+
+hfiles = libc.h \
+
+<$LPLAN9/src/mklib
diff --git a/start.s b/start.s
@@ -0,0 +1,19 @@
+.intel_syntax noprefix
+.global _start
+.text
+
+_start:
+ xor rbp, rbp
+ pop rdi
+ mov rsi, rsp
+
+ lea rdx, [rsi + rdi*8 + 8]
+
+ call main
+
+ # exit(rax)
+ mov rdi, rax
+ mov rax, 60
+ syscall
+
+ jmp .
diff --git a/strlen.c b/strlen.c
@@ -0,0 +1,13 @@
+/*
+ * strlen.c — get string length
+ * Copyright (C) 2026. All rights reserved.
+ */
+
+#include "libc.h"
+
+size_t strlen(const char* str) {
+ size_t len = 0;
+ while (str[len])
+ len++;
+ return len;
+}
diff --git a/wrapers/cc b/wrapers/cc
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+INC=$(cc -print-file-name=include)
+exec cc -nostdlib -nostdinc -ffreestanding -fno-builtin -isystem "$INC" "$@"
diff --git a/write.c b/write.c
@@ -0,0 +1,19 @@
+/*
+ * write.c — write system call
+ * Copyright (C) 2026. All rights reserved.
+ */
+
+#include "libc.h"
+
+ssize_t write(int fd, const void *buf, size_t count) {
+ long ret;
+
+ asm volatile (
+ "syscall"
+ : "=a"(ret)
+ : "a"(sys_write), "D"(fd), "S"(buf), "d"(count)
+ : "rcx", "r11", "memory"
+ );
+
+ return ret;
+}