ports: qbe, cproc :^)

This commit is contained in:
dzwdz 2023-08-27 02:06:32 +02:00
parent 1f938c20b4
commit e43939bcc6
28 changed files with 360 additions and 31 deletions

View File

@ -0,0 +1,26 @@
static const char target[] = "x86_64-camellia";
static const char *const startfiles[] = {"-l", ":crt0.o"};
static const char *const endfiles[] = {"-l", "c"};
static const char *const preprocesscmd[] = {
"cpp",
/* clear preprocessor GNU C version */
"-U", "__GNUC__",
"-U", "__GNUC_MINOR__",
/* we don't yet support these optional features */
"-D", "__STDC_NO_ATOMICS__",
"-D", "__STDC_NO_COMPLEX__",
"-D", "__STDC_NO_VLA__",
"-U", "__SIZEOF_INT128__",
/* we don't generate position-independent code */
"-U", "__PIC__",
/* ignore attributes and extension markers */
"-D", "__attribute__(x)=",
"-D", "__extension__=",
};
static const char *const codegencmd[] = {"qbe"};
static const char *const assemblecmd[] = {"as"};
static const char *const linkcmd[] = {"ld", "-no-dynamic-linker", "-pie"};

View File

@ -0,0 +1,5 @@
PREFIX=/usr/
BINDIR=$(PREFIX)/bin
CC=cc
CFLAGS=-std=c99 -Wall -Wpedantic -Wno-parentheses -Wno-switch -g -pipe
LDFLAGS=

View File

@ -0,0 +1,17 @@
--- driver.c.orig
+++ driver.c
@@ -165,12 +165,10 @@ spawnphase(struct stageinfo *phase, int *fd, char *input, char *output, bool las
goto err1;
}
if (fcntl(pipefd[0], F_SETFD, FD_CLOEXEC) < 0) {
- ret = errno;
- goto err2;
+ warn("fcntl(..., F_SETFD, FD_CLOEXEC):");
}
if (fcntl(pipefd[1], F_SETFD, FD_CLOEXEC) < 0) {
- ret = errno;
- goto err2;
+ warn("fcntl(..., F_SETFD, FD_CLOEXEC):");
}
ret = posix_spawn_file_actions_adddup2(&actions, pipefd[1], 1);
if (ret)

13
ports/cproc/port Executable file
View File

@ -0,0 +1,13 @@
#!/bin/sh
. ports/pre
pkg=cproc
tarball=michaelforney-cproc-0985a78.tar.gz
tarball_dir=michaelforney-cproc-0985a78
url=https://github.com/michaelforney/cproc/tarball/0985a7893a4b5de63a67ebab445892d9fffe275b
relink() {
rm $tarball_dir/cproc
}
. ports/post

1
ports/cproc/sha256sums Normal file
View File

@ -0,0 +1 @@
cf9a4de550303eedcc8b8ee22f11b085a9387b911fa16a6fa7551382a3d7a1ea michaelforney-cproc-0985a78.tar.gz

13
ports/qbe/port Executable file
View File

@ -0,0 +1,13 @@
#!/bin/sh
. ports/pre
pkg=qbe
tarball=qbe-1.1.tar.xz
tarball_dir=qbe-1.1
url=https://c9x.me/compile/release/$tarball
relink() {
rm $tarball_dir/qbe
}
. ports/post

1
ports/qbe/sha256sums Normal file
View File

@ -0,0 +1 @@
7d0a53dd40df48072aae317e11ddde15d1a980673160e514e235b9ecaa1db12c qbe-1.1.tar.xz

View File

@ -1,3 +1,4 @@
#include <camellia/errno.h>
#include <kernel/panic.h>
#include <kernel/pipe.h>
#include <kernel/util.h>
@ -8,7 +9,7 @@ void pipe_joinqueue(Handle *h, Proc *proc, void __user *pbuf, size_t pbuflen) {
assert(h && h->type == HANDLE_PIPE);
assert(h->readable ^ h->writeable);
if (!h->pipe.sister) {
regs_savereturn(&proc->regs, -1);
regs_savereturn(&proc->regs, h->readable ? 0 : -EPIPE);
return;
}

View File

@ -349,10 +349,14 @@ void proc_tryreap(Proc *dead) {
if (parent->state != PS_WAITS4CHILDDEATH) {
return; /* don't reap yet */
}
uint32_t pid = proc_ns_id(parent->pns, dead);
if (parent->awaited_death.pid && parent->awaited_death.pid != pid) {
return; /* we're not The One */
}
if (parent->awaited_death.legacy) {
regs_savereturn(&parent->regs, dead->death_msg);
} else {
regs_savereturn(&parent->regs, proc_ns_id(parent->pns, dead));
regs_savereturn(&parent->regs, pid);
if (parent->awaited_death.out) {
struct sys_wait2 __user *out = parent->awaited_death.out;
struct sys_wait2 data;

View File

@ -46,6 +46,7 @@ struct Proc {
int death_msg; // PS_DEAD
struct {
bool legacy; /* false = wait2, true = await */
uint32_t pid; /* valid if nonzero */
struct sys_wait2 __user *out;
} awaited_death;
struct {

View File

@ -26,6 +26,7 @@ long _sys_await(void) {
bool has_children = false;
proc_setstate(proc_cur, PS_WAITS4CHILDDEATH);
proc_cur->awaited_death.legacy = true;
proc_cur->awaited_death.pid = 0;
for (Proc *iter = proc_cur->child;
iter; iter = iter->sibling)
@ -403,7 +404,7 @@ uint32_t _sys_getppid(void) {
}
int _sys_wait2(int pid, int flags, struct sys_wait2 __user *out) {
if (pid != -1 || flags != 0) {
if (flags != 0) {
SYSCALL_RETURN(-ENOSYS);
}
@ -411,13 +412,13 @@ int _sys_wait2(int pid, int flags, struct sys_wait2 __user *out) {
proc_setstate(proc_cur, PS_WAITS4CHILDDEATH);
proc_cur->awaited_death.legacy = false;
proc_cur->awaited_death.out = out;
proc_cur->awaited_death.pid = (0 < pid) ? pid : 0;
for (Proc *iter = proc_cur->child; iter; iter = iter->sibling) {
if (iter->noreap) continue;
has_children = true;
if (iter->state == PS_TOREAP) {
proc_tryreap(iter);
return 0; // dummy
}
}

View File

@ -8,6 +8,10 @@ int isalpha(int c) {
return islower(c) || isupper(c);
}
int isblank(int c) {
return c == ' ' || c == '\t';
}
int iscntrl(int c) {
return c <= 0x1f || c == 0x7f;
}

View File

@ -42,19 +42,22 @@ static bool valid_ehdr(const struct Elf64_Ehdr *h) {
static bool load_phdr(const void *elf, void *exebase, size_t idx) {
const struct Elf64_Ehdr *ehdr = elf;
const struct Elf64_Phdr *phdr = elf + ehdr->e_phoff + idx * ehdr->e_phentsize;
if (phdr->p_type == PT_DYNAMIC) return true;
if (phdr->p_type != PT_LOAD) {
printf("unknown type %x\n", phdr->p_type);
switch (phdr->p_type) {
case PT_DYNAMIC:
case 0x6474e551: /* GNU_STACK */
return true;
case PT_LOAD:
// TODO overlap check
// TODO don't ignore flags
_sys_memflag(exebase + phdr->p_vaddr, phdr->p_memsz, MEMFLAG_PRESENT);
// TODO check that filesz <= memsz
memcpy(exebase + phdr->p_vaddr, elf + phdr->p_offset, phdr->p_filesz);
return true;
default:
printf("unknown elf phdr %x\n", phdr->p_type);
return false;
}
// TODO overlap check
// TODO don't ignore flags
_sys_memflag(exebase + phdr->p_vaddr, phdr->p_memsz, MEMFLAG_PRESENT);
// TODO check that filesz <= memsz
memcpy(exebase + phdr->p_vaddr, elf + phdr->p_offset, phdr->p_filesz);
return true;
}
static size_t elf_spread(const void *elf) {

View File

@ -2,6 +2,7 @@
int isalnum(int c);
int isalpha(int c);
int isblank(int c);
int iscntrl(int c);
int isdigit(int c);
int isgraph(int c);

View File

@ -1,6 +1,7 @@
#include <stdint.h>
#define PRId64 "ld"
#define PRIi64 "li"
#define PRIo64 "lo"
#define PRIu64 "lu"
#define PRIx64 "lx"
@ -9,11 +10,13 @@
#define PRId32 "d"
#define PRIo32 "o"
#define PRIu32 "u"
#define PRIuLEAST32 "u"
#define PRIx32 "x"
#define SCNu32 "u"
#define PRId16 "d"
#define PRIo16 "o"
#define PRIu16 "u"
#define PRIuLEAST16 "u"
#define PRIx16 "x"
#define SCNu16 "u"

21
src/libc/include/spawn.h Normal file
View File

@ -0,0 +1,21 @@
#pragma once
#include <sys/types.h>
typedef struct {
struct file_action *f;
} posix_spawn_file_actions_t;
typedef struct {} posix_spawnattr_t;
int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *facts, int from, int to);
int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *facts);
int posix_spawn_file_actions_init(posix_spawn_file_actions_t *facts);
int posix_spawnp(
pid_t *restrict pid,
const char *restrict file,
const posix_spawn_file_actions_t *restrict file_actions,
const posix_spawnattr_t *restrict attrp,
char *const argv[restrict],
char *const envp[restrict]
);

View File

@ -1,4 +1,5 @@
#pragma once
#include <bits/file.h>
#include <stdarg.h>
#include <stddef.h>
@ -27,6 +28,7 @@ int printf(const char *restrict fmt, ...);
int fprintf(FILE *restrict f, const char *restrict fmt, ...);
int sprintf(char *restrict s, const char *restrict fmt, ...);
int snprintf(char *restrict str, size_t len, const char *restrict fmt, ...);
int vprintf(const char *restrict fmt, va_list ap);
int vsprintf(char *restrict s, const char *restrict fmt, va_list ap);
@ -86,4 +88,6 @@ char *tmpnam(char *s);
int sscanf(const char *restrict s, const char *restrict format, ...);
int vsscanf(const char* str, const char* format, va_list ap);
int fscanf(FILE* fp, const char* format, ...);
int vfscanf(FILE* fp, const char* format, va_list ap);
int vcbscanf(void* fp, int (*fgetc)(void*), int (*ungetc)(int, void*), const char* restrict format, va_list ap);

View File

@ -27,3 +27,4 @@ char *strdup(const char *s);
size_t strnlen(const char *s, size_t len);
char *strerror(int errnum);
char *strsignal(int sig);

View File

@ -4,6 +4,7 @@
#define WIFSTOPPED(x) 0
#define WEXITSTATUS(x) ((x)&0xFF)
#define WIFEXITED(x) 1
#define WIFSIGNALED(x) 0
#define WSTOPSIG(x) 0
#define WTERMSIG(x) 0
@ -12,3 +13,4 @@
pid_t wait(int *wstatus);
pid_t wait3(int *wstatus, int opts, struct rusage *rusage);
pid_t waitpid(pid_t pid, int *wstatus, int opts);

View File

@ -22,6 +22,7 @@ int isatty(int fd);
int execv(const char *path, char *const argv[]);
int execvp(const char *path, char *const argv[]);
int execvpe(const char *path, char *const argv[], char *const envp[]);
int execve(const char *path, char *const argv[], char *const envp[]);
int chdir(const char *path);

82
src/libc/spawn.c Normal file
View File

@ -0,0 +1,82 @@
#include <camellia/syscalls.h>
#include <errno.h>
#include <spawn.h>
#include <stdlib.h>
#include <unistd.h>
enum act {
ACT_DUP2 = 1,
};
struct file_action {
struct file_action *next;
enum act type;
int a, b;
};
int
posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *facts, int from, int to)
{
struct file_action *fact, **tail;
fact = calloc(1, sizeof(*fact));
if (!fact) return ENOMEM;
fact->type = ACT_DUP2;
fact->a = from;
fact->b = to;
tail = &facts->f;
while (*tail) {
tail = &(*tail)->next;
}
*tail = fact;
return 0;
}
int
posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *facts)
{
while (facts->f) {
struct file_action *cur = facts->f;
facts->f = cur->next;
free(cur);
}
return 0;
}
int
posix_spawn_file_actions_init(posix_spawn_file_actions_t *facts)
{
facts->f = NULL;
return 0;
}
int
posix_spawnp(
pid_t *restrict pidp,
const char *restrict file,
const posix_spawn_file_actions_t *restrict facts,
const posix_spawnattr_t *restrict attrp,
char *const argv[restrict],
char *const envp[restrict]
) {
if (attrp) return ENOSYS;
pid_t pid = fork();
if (pid < 0) return errno;
if (pid == 0) {
struct file_action *fact = facts ? facts->f : NULL;
while (fact) {
switch (fact->type) {
case ACT_DUP2:
dup2(fact->a, fact->b);
break;
}
fact = fact->next;
}
execvpe(file, argv, envp);
_sys_exit(127);
}
if (pidp) *pidp = pid;
return 0;
}

View File

@ -248,7 +248,7 @@ size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restri
}
int fputs(const char *s, FILE *f) {
return fprintf(f, "%s\n", s);
return fprintf(f, "%s", s);
}
char *fgets(char *buf, int size, FILE *f) {

View File

@ -124,6 +124,12 @@ size_t strnlen(const char *s, size_t len) {
return len;
}
char *strsignal(int sig) {
static char buf[32];
snprintf(buf, sizeof(buf), "signal %d", sig);
return buf;
}
/* strings.h */
int strcasecmp(const char *s1, const char *s2) {
return strncasecmp(s1, s2, ~0);

View File

@ -10,11 +10,18 @@ pid_t wait(int *wstatus) {
}
pid_t wait3(int *wstatus, int opts, struct rusage *rusage) {
struct sys_wait2 res;
if (opts || rusage) {
if (rusage) {
__libc_panic("unimplemented");
}
pid_t ret = _sys_wait2(-1, 0, &res);
return waitpid(-1, wstatus, opts);
}
pid_t waitpid(pid_t pid, int *wstatus, int opts) {
struct sys_wait2 res;
if (opts) {
__libc_panic("unimplemented");
}
pid_t ret = _sys_wait2(pid, 0, &res);
if (ret < 0) {
errno = -ret;
return -1;

View File

@ -77,6 +77,19 @@ int execvp(const char *path, char *const argv[]) {
return execve(path, argv, NULL);
}
int execvpe(const char *path, char *const argv[], char *const envp[]) {
if (path[0] != '/') {
char *exp = malloc(strlen(path) + 6);
int ret;
strcpy(exp, "/bin/");
strcat(exp, path);
ret = execve(exp, argv, envp);
free(exp);
return ret;
}
return execve(path, argv, envp);
}
int execve(const char *path, char *const argv[], char *const envp[]) {
FILE *file = fopen(path, "e");
char hdr[4] = {0};
@ -225,8 +238,13 @@ ssize_t write(int fd, const void *buf, size_t count) {
}
int pipe(int pipefd[2]) {
(void)pipefd;
__libc_panic("unimplemented");
// TODO pipe buffering
int ret = _sys_pipe(pipefd, 0);
if (ret < 0) {
errno = -ret;
return -1;
}
return 0;
}
int dup(int oldfd) {
@ -235,8 +253,12 @@ int dup(int oldfd) {
}
int dup2(int oldfd, int newfd) {
(void)oldfd; (void)newfd;
__libc_panic("unimplemented");
int ret = _sys_dup(oldfd, newfd, 0);
if (ret < 0) {
errno = -ret;
ret = -1;
}
return ret;
}
unsigned int sleep(unsigned int seconds) {

30
src/libc/vendor/sortix/fscanf.c vendored Normal file
View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2012, 2013 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* stdio/fscanf.c
* Input format conversion.
*/
#include <stdarg.h>
#include <stdio.h>
int fscanf(FILE* fp, const char* format, ...)
{
va_list ap;
va_start(ap, format);
int ret = vfscanf(fp, format, ap);
va_end(ap);
return ret;
}

43
src/libc/vendor/sortix/vfscanf.c vendored Normal file
View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2012, 2013, 2014 Jonas 'Sortie' Termansen.
* Modified by dzwdz.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* stdio/vfscanf.c
* Input format conversion.
*
* stdio/vfscanf_unlocked.c
* Input format conversion.
*/
#include <errno.h>
#include <stdio.h>
static int wrap_fgetc(void* fp)
{
return fgetc((FILE*) fp);
}
static int wrap_ungetc(int c, void* fp)
{
return ungetc(c, (FILE*) fp);
}
int vfscanf(FILE* fp, const char* format, va_list ap)
{
// if ( !(fp->flags & _FILE_READABLE) )
// return errno = EBADF, fp->flags |= _FILE_STATUS_ERROR, EOF;
return vcbscanf(fp, wrap_fgetc, wrap_ungetc, format, ap);
}

View File

@ -96,6 +96,22 @@ static void output_uint16(struct out_state *os, struct mods *m, unsigned long lo
}
}
static void output_octal(struct out_state *os, struct mods *m, unsigned long long n) {
char buf[sizeof(unsigned long long) * 3];
size_t pos = sizeof(buf);
if (!n) {
buf[--pos] = '0';
} else while (n) {
unsigned long long q = n / 8, r = n % 8;
buf[--pos] = r + '0';
n = q;
}
size_t len = sizeof(buf) - pos;
padnum(os, m, len, '\0');
output(os, buf + pos, len);
}
int __printf_internal(const char *fmt, va_list argp,
void (*back)(void*, const char*, size_t), void *backarg)
@ -170,6 +186,10 @@ int __printf_internal(const char *fmt, va_list argp,
lm = LM_size;
c = *fmt++;
break;
case 'j':
lm = LM_longlong;
c = *fmt++;
break;
default:
lm = LM_int;
break;
@ -201,19 +221,15 @@ int __printf_internal(const char *fmt, va_list argp,
break;
case 'x':
if (lm == LM_int) n = va_arg(argp, unsigned int);
else if (lm == LM_long) n = va_arg(argp, unsigned long);
else if (lm == LM_longlong) n = va_arg(argp, unsigned long long);
else if (lm == LM_size) n = va_arg(argp, size_t);
output_uint16(&os, &m, n);
break;
case 'u':
case 'o':
if (lm == LM_int) n = va_arg(argp, unsigned int);
else if (lm == LM_long) n = va_arg(argp, unsigned long);
else if (lm == LM_longlong) n = va_arg(argp, unsigned long long);
else if (lm == LM_size) n = va_arg(argp, size_t);
output_uint(&os, &m, n, '\0');
if (c == 'x') output_uint16(&os, &m, n);
if (c == 'u') output_uint(&os, &m, n, '\0');
if (c == 'o') output_octal(&os, &m, n);
break;
case 'd':