/* start.c - Minimal libc for Pactor64 userspace * * Provides _start entry point, syscall wrappers, string functions, * printf, and bump allocator. */ #include "libc.h" /* Syscall numbers (Linux x86-64 compatible) */ #define SYS_READ 0 #define SYS_WRITE 1 #define SYS_BRK 12 #define SYS_EXIT 60 /* Inline syscall instruction */ static inline long __syscall1(long num, long a1) { long ret; __asm__ volatile ( "syscall" : "=a"(ret) : "a"(num), "D"(a1) : "rcx", "r11", "memory" ); return ret; } static inline long __syscall3(long num, long a1, long a2, long a3) { long ret; __asm__ volatile ( "syscall" : "=a"(ret) : "a"(num), "D"(a1), "S"(a2), "d"(a3) : "rcx", "r11", "memory" ); return ret; } /* === System call wrappers === */ long write(int fd, const void *buf, unsigned long count) { return __syscall3(SYS_WRITE, fd, (long)buf, (long)count); } long read(int fd, void *buf, unsigned long count) { return __syscall3(SYS_READ, fd, (long)buf, (long)count); } void exit(int status) { __syscall1(SYS_EXIT, status); __builtin_unreachable(); } long brk(void *addr) { return __syscall1(SYS_BRK, (long)addr); } /* === String functions === */ unsigned long strlen(const char *s) { unsigned long len = 0; while (s[len]) len++; return len; } int strcmp(const char *s1, const char *s2) { while (*s1 && *s1 == *s2) { s1++; s2++; } return (unsigned char)*s1 - (unsigned char)*s2; } int strncmp(const char *s1, const char *s2, unsigned long n) { while (n && *s1 && *s1 == *s2) { s1++; s2++; n--; } return n ? (unsigned char)*s1 - (unsigned char)*s2 : 0; } char *strcpy(char *dst, const char *src) { char *ret = dst; while ((*dst++ = *src++)); return ret; } char *strncpy(char *dst, const char *src, unsigned long n) { char *ret = dst; while (n && (*dst++ = *src++)) n--; while (n--) *dst++ = '\0'; return ret; } void *memset(void *s, int c, unsigned long n) { unsigned char *p = (unsigned char *)s; while (n--) *p++ = (unsigned char)c; return s; } void *memcpy(void *dst, const void *src, unsigned long n) { unsigned char *d = (unsigned char *)dst; const unsigned char *s = (const unsigned char *)src; while (n--) *d++ = *s++; return dst; } void *memmove(void *dst, const void *src, unsigned long n) { unsigned char *d = (unsigned char *)dst; const unsigned char *s = (const unsigned char *)src; if (d < s) { while (n--) *d++ = *s++; } else { d += n; s += n; while (n--) *--d = *--s; } return dst; } /* === Bump allocator === */ static void *heap_start = 0; static void *heap_end = 0; static void *heap_current = 0; static void heap_init(void) { heap_start = (void *)0x400000; /* Start at 4MB */ heap_end = (void *)0x10000000; /* Up to 256MB */ heap_current = heap_start; brk(heap_end); } void *malloc(unsigned long size) { if (heap_start == 0) heap_init(); /* Align to 16 bytes */ size = (size + 15) & ~15UL; void *ptr = heap_current; heap_current = (void *)((unsigned long)heap_current + size); if (heap_current > heap_end) { /* Out of memory */ return 0; } return ptr; } void free(void *ptr) { /* Bump allocator - no-op for simplicity */ (void)ptr; } /* === I/O === */ int putchar(int c) { char ch = (char)c; write(1, &ch, 1); return c; } int puts(const char *s) { unsigned long len = strlen(s); write(1, s, len); putchar('\n'); return (int)(len + 1); } /* === printf === */ static void print_string(const char *s) { if (!s) s = "(null)"; write(1, s, strlen(s)); } static void print_dec(unsigned long val) { char buf[21]; int i = 0; if (val == 0) { putchar('0'); return; } while (val > 0) { buf[i++] = '0' + (val % 10); val /= 10; } while (i > 0) putchar(buf[--i]); } static void print_signed_dec(long val) { if (val < 0) { putchar('-'); print_dec((unsigned long)-val); } else { print_dec((unsigned long)val); } } static void print_hex(unsigned long val) { char buf[17]; int i = 0; if (val == 0) { putchar('0'); return; } while (val > 0) { int digit = val & 0xF; buf[i++] = digit < 10 ? '0' + digit : 'a' + digit - 10; val >>= 4; } while (i > 0) putchar(buf[--i]); } int printf(const char *fmt, ...) { va_list ap; va_start(ap, fmt); int count = 0; for (int i = 0; fmt[i]; i++) { if (fmt[i] == '%' && fmt[i + 1]) { i++; switch (fmt[i]) { case 'd': print_signed_dec(va_arg(ap, long)); break; case 'u': print_dec(va_arg(ap, unsigned long)); break; case 'x': print_hex(va_arg(ap, unsigned long)); break; case 's': print_string(va_arg(ap, const char *)); break; case 'c': putchar((char)va_arg(ap, int)); break; case '%': putchar('%'); break; default: putchar('%'); putchar(fmt[i]); break; } } else { putchar(fmt[i]); count++; } } va_end(ap); return count; } /* === Entry point === */ void _start(void) { int ret = main(0, 0); exit(ret); }