libc

libc
git clone http://194.87.232.205/libc
Log | Files | Refs | README

commit dbbe4055eb52d042e3f4c5befd3d4ce5d2675af4
Author: evenfri <evenfri256@gmail.com>
Date:   Fri, 24 Jul 2026 01:05:53 +0800

initial commit

Diffstat:
A.gitignore | 4++++
AREADME | 45+++++++++++++++++++++++++++++++++++++++++++++
A_exit.c | 17+++++++++++++++++
Aexample/main.c | 7+++++++
Aexample/mkfile | 9+++++++++
Aexit.c | 10++++++++++
Alibc.h | 33+++++++++++++++++++++++++++++++++
Amkfile | 16++++++++++++++++
Astart.s | 19+++++++++++++++++++
Astrlen.c | 13+++++++++++++
Awrapers/cc | 4++++
Awrite.c | 19+++++++++++++++++++
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; +}