start.c

Commit: 347e967b Author: jokerz Raw Copy
1
/* start.c - Minimal libc for Pactor64 userspace
2
 *
3
 * Provides _start entry point, syscall wrappers, string functions,
4
 * printf, and bump allocator.
5
 */
6
#include "libc.h"
7
8
/* Syscall numbers (Linux x86-64 compatible) */
9
#define SYS_READ   0
10
#define SYS_WRITE  1
11
#define SYS_BRK    12
12
#define SYS_EXIT   60
13
14
/* Inline syscall instruction */
15
static inline long __syscall1(long num, long a1) {
16
    long ret;
17
    __asm__ volatile (
18
        "syscall"
19
        : "=a"(ret)
20
        : "a"(num), "D"(a1)
21
        : "rcx", "r11", "memory"
22
    );
23
    return ret;
24
}
25
26
static inline long __syscall3(long num, long a1, long a2, long a3) {
27
    long ret;
28
    __asm__ volatile (
29
        "syscall"
30
        : "=a"(ret)
31
        : "a"(num), "D"(a1), "S"(a2), "d"(a3)
32
        : "rcx", "r11", "memory"
33
    );
34
    return ret;
35
}
36
37
/* === System call wrappers === */
38
39
long write(int fd, const void *buf, unsigned long count) {
40
    return __syscall3(SYS_WRITE, fd, (long)buf, (long)count);
41
}
42
43
long read(int fd, void *buf, unsigned long count) {
44
    return __syscall3(SYS_READ, fd, (long)buf, (long)count);
45
}
46
47
void exit(int status) {
48
    __syscall1(SYS_EXIT, status);
49
    __builtin_unreachable();
50
}
51
52
long brk(void *addr) {
53
    return __syscall1(SYS_BRK, (long)addr);
54
}
55
56
/* === String functions === */
57
58
unsigned long strlen(const char *s) {
59
    unsigned long len = 0;
60
    while (s[len]) len++;
61
    return len;
62
}
63
64
int strcmp(const char *s1, const char *s2) {
65
    while (*s1 && *s1 == *s2) { s1++; s2++; }
66
    return (unsigned char)*s1 - (unsigned char)*s2;
67
}
68
69
int strncmp(const char *s1, const char *s2, unsigned long n) {
70
    while (n && *s1 && *s1 == *s2) { s1++; s2++; n--; }
71
    return n ? (unsigned char)*s1 - (unsigned char)*s2 : 0;
72
}
73
74
char *strcpy(char *dst, const char *src) {
75
    char *ret = dst;
76
    while ((*dst++ = *src++));
77
    return ret;
78
}
79
80
char *strncpy(char *dst, const char *src, unsigned long n) {
81
    char *ret = dst;
82
    while (n && (*dst++ = *src++)) n--;
83
    while (n--) *dst++ = '\0';
84
    return ret;
85
}
86
87
void *memset(void *s, int c, unsigned long n) {
88
    unsigned char *p = (unsigned char *)s;
89
    while (n--) *p++ = (unsigned char)c;
90
    return s;
91
}
92
93
void *memcpy(void *dst, const void *src, unsigned long n) {
94
    unsigned char *d = (unsigned char *)dst;
95
    const unsigned char *s = (const unsigned char *)src;
96
    while (n--) *d++ = *s++;
97
    return dst;
98
}
99
100
void *memmove(void *dst, const void *src, unsigned long n) {
101
    unsigned char *d = (unsigned char *)dst;
102
    const unsigned char *s = (const unsigned char *)src;
103
    if (d < s) {
104
        while (n--) *d++ = *s++;
105
    } else {
106
        d += n; s += n;
107
        while (n--) *--d = *--s;
108
    }
109
    return dst;
110
}
111
112
/* === Bump allocator === */
113
114
static void *heap_start = 0;
115
static void *heap_end = 0;
116
static void *heap_current = 0;
117
118
static void heap_init(void) {
119
    heap_start = (void *)0x400000;  /* Start at 4MB */
120
    heap_end = (void *)0x10000000;  /* Up to 256MB */
121
    heap_current = heap_start;
122
    brk(heap_end);
123
}
124
125
void *malloc(unsigned long size) {
126
    if (heap_start == 0) heap_init();
127
128
    /* Align to 16 bytes */
129
    size = (size + 15) & ~15UL;
130
131
    void *ptr = heap_current;
132
    heap_current = (void *)((unsigned long)heap_current + size);
133
134
    if (heap_current > heap_end) {
135
        /* Out of memory */
136
        return 0;
137
    }
138
139
    return ptr;
140
}
141
142
void free(void *ptr) {
143
    /* Bump allocator - no-op for simplicity */
144
    (void)ptr;
145
}
146
147
/* === I/O === */
148
149
int putchar(int c) {
150
    char ch = (char)c;
151
    write(1, &ch, 1);
152
    return c;
153
}
154
155
int puts(const char *s) {
156
    unsigned long len = strlen(s);
157
    write(1, s, len);
158
    putchar('\n');
159
    return (int)(len + 1);
160
}
161
162
/* === printf === */
163
164
static void print_string(const char *s) {
165
    if (!s) s = "(null)";
166
    write(1, s, strlen(s));
167
}
168
169
static void print_dec(unsigned long val) {
170
    char buf[21];
171
    int i = 0;
172
    if (val == 0) { putchar('0'); return; }
173
    while (val > 0) {
174
        buf[i++] = '0' + (val % 10);
175
        val /= 10;
176
    }
177
    while (i > 0) putchar(buf[--i]);
178
}
179
180
static void print_signed_dec(long val) {
181
    if (val < 0) {
182
        putchar('-');
183
        print_dec((unsigned long)-val);
184
    } else {
185
        print_dec((unsigned long)val);
186
    }
187
}
188
189
static void print_hex(unsigned long val) {
190
    char buf[17];
191
    int i = 0;
192
    if (val == 0) { putchar('0'); return; }
193
    while (val > 0) {
194
        int digit = val & 0xF;
195
        buf[i++] = digit < 10 ? '0' + digit : 'a' + digit - 10;
196
        val >>= 4;
197
    }
198
    while (i > 0) putchar(buf[--i]);
199
}
200
201
int printf(const char *fmt, ...) {
202
    va_list ap;
203
    va_start(ap, fmt);
204
    int count = 0;
205
206
    for (int i = 0; fmt[i]; i++) {
207
        if (fmt[i] == '%' && fmt[i + 1]) {
208
            i++;
209
            switch (fmt[i]) {
210
                case 'd':
211
                    print_signed_dec(va_arg(ap, long));
212
                    break;
213
                case 'u':
214
                    print_dec(va_arg(ap, unsigned long));
215
                    break;
216
                case 'x':
217
                    print_hex(va_arg(ap, unsigned long));
218
                    break;
219
                case 's':
220
                    print_string(va_arg(ap, const char *));
221
                    break;
222
                case 'c':
223
                    putchar((char)va_arg(ap, int));
224
                    break;
225
                case '%':
226
                    putchar('%');
227
                    break;
228
                default:
229
                    putchar('%');
230
                    putchar(fmt[i]);
231
                    break;
232
            }
233
        } else {
234
            putchar(fmt[i]);
235
            count++;
236
        }
237
    }
238
    va_end(ap);
239
    return count;
240
}
241
242
/* === Entry point === */
243
244
void _start(void) {
245
    int ret = main(0, 0);
246
    exit(ret);
247
}
248