From 8d1e6938845a8e4c131775101f2ec0d0f81aa4d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Lov=C3=A9n?= Date: Thu, 9 Feb 2017 19:47:07 +0100 Subject: [PATCH] [TOOLCHAIN] Making musl portable --- Makefile | 7 +++- init/Makefile | 2 + init/init.c | 2 +- kernel/syscall/syscall.c | 3 +- libc/Makefile | 21 ++++++++-- libc/syscall_num.h | 3 ++ libc/syscalls.c | 53 +++++++++++++++++++++++++ libc/syscalls.h | 36 +++++++++++++++++ util/build_toolchain.sh | 2 + util/patch_musl.sh | 84 ++++++++++++++++++++++++++++++++++++++++ 10 files changed, 207 insertions(+), 6 deletions(-) create mode 100644 libc/syscall_num.h create mode 100644 libc/syscalls.c create mode 100644 libc/syscalls.h create mode 100755 util/patch_musl.sh diff --git a/Makefile b/Makefile index b98ab5b..e7b53b1 100644 --- a/Makefile +++ b/Makefile @@ -8,8 +8,12 @@ endif SHELL := bash CC=$(TARGET)-gcc +AR=$(TARGET)-ar +LD=$(TARGET)-ld FLAGS_TO_PASS:= \ - CC=$(CC) + CC=$(CC) \ + AR=$(AR) \ + LD=$(LD) all: kernel libc init @@ -24,6 +28,7 @@ libc: ifeq ($(shell make -sqC libc || echo 1), 1) @(. util/helpers.sh; print_info "Building c library") $(MAKE) -C libc install $(FLAGS_TO_PASS) + $(MAKE) $(MAKECMDGOALS) endif init: diff --git a/init/Makefile b/init/Makefile index f9e5c58..c4a3999 100644 --- a/init/Makefile +++ b/init/Makefile @@ -11,6 +11,8 @@ CFLAGS ?= -Wall -Wextra -ggdb -O0 all: init +init: $(SYSROOT)/usr/lib/libc.a + $(installdir)/init: init mkdir -p $(dir $@) cp $< $@ diff --git a/init/init.c b/init/init.c index ac1298a..1f4bf37 100644 --- a/init/init.c +++ b/init/init.c @@ -4,7 +4,7 @@ int main(int argc, char **argv) { (void) argc; (void) argv; - asm("syscall" :: "a" (0x3FF), "D" ("Hello, world!\n")); + fork(); for(;;); return 0; } diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index 904f00a..89fbdc5 100644 --- a/kernel/syscall/syscall.c +++ b/kernel/syscall/syscall.c @@ -4,6 +4,7 @@ #include #include #include +#include "../../libc/syscall_num.h" extern void syscall_entry(); @@ -52,7 +53,7 @@ void syscall_init() syscall_installed = 1; memset(syscall_handlers, 0, 1024*sizeof(syscall_handler_t)); - SYSCALL_REGISTER(debug, 0x3FF); + SYSCALL_REGISTER(debug, SYS_DEBUG); } } diff --git a/libc/Makefile b/libc/Makefile index 1ee77b5..72f6a78 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -3,26 +3,41 @@ ifeq ($(MITTOS64),) endif LIBDIR := $(SYSROOT)/usr/lib +LIBC := $(LIBDIR)/libc.a CRT := crt0 CRT_OBJ := $(addprefix obj/, $(patsubst %,%.o,$(CRT))) +SRC := $(filter-out $(CRT).%, $(wildcard *.[cS])) +OBJ := $(addprefix obj/, $(patsubst %,%.o, $(basename $(SRC)))) +libfile := mittos64.o +LIB_OBJ := $(LIBC)($(libfile)) + +CFLAGS := -Wall -Wextra -ggdb -O0 ASFLAGS := -ggdb -all: $(CRT_OBJ) +all: $(CRT_OBJ) $(OBJ) -OBJ_DIRS := $(sort $(dir $(CRT_OBJ))) +OBJ_DIRS := $(sort $(dir $(CRT_OBJ) $(OBJ))) $(CRT_OBJ): | $(OBJ_DIRS) $(OBJ_DIRS): mkdir -p $@ +obj/%.o:%.c + $(COMPILE.c) $^ -o $@ obj/%.o:%.S $(COMPILE.S) $^ -o $@ +obj/$(libfile):$(OBJ) + $(LD) -r $^ -o $@ + +$(LIBC)(%):obj/% + $(AR) -d $@ $< + $(AR) -rs $@ $< $(LIBDIR)/%: obj/% cp $< $@ -install: $(patsubst %,$(LIBDIR)/%.o,$(CRT)) +install: $(patsubst %,$(LIBDIR)/%.o,$(CRT)) $(LIB_OBJ) clean: rm -rf obj/ diff --git a/libc/syscall_num.h b/libc/syscall_num.h new file mode 100644 index 0000000..62fbd1d --- /dev/null +++ b/libc/syscall_num.h @@ -0,0 +1,3 @@ +#pragma once + +#define SYS_DEBUG 0x3FF diff --git a/libc/syscalls.c b/libc/syscalls.c new file mode 100644 index 0000000..4502984 --- /dev/null +++ b/libc/syscalls.c @@ -0,0 +1,53 @@ +#include +#include +#include "syscalls.h" + +long kernel_syscall(int num, ...) +{ + va_list varg; + va_start(varg, num); + long a1 = va_arg(varg, long); + long a2 = va_arg(varg, long); + long a3 = va_arg(varg, long); + register long r10 __asm__("r10") = va_arg(varg, long); + register long r8 __asm__("r8") = va_arg(varg, long); + register long r9 __asm__("r9") = va_arg(varg, long); + va_end(varg); + + long ret; + __asm__ __volatile__("syscall" : "=a" (ret) : "a" (num), "D" (a1), "S" (a2), "d" (a3), "r" (r10), "r" (r8), "r" (r9) : "rcx", "r11", "memory"); + return ret; +} + +char debug_buffer[256]; +void kernel_debug(char *fmt, ...) +{ + va_list varg; + va_start(varg, fmt); + vsprintf(debug_buffer, fmt, varg); + va_end(varg); + kernel_syscall(SYS_DEBUG, (long)debug_buffer); +} + +long __syscall_common(long num, ...) +{ + va_list varg; + va_start(varg, num); + long a1 = va_arg(varg, long); + long a2 = va_arg(varg, long); + long a3 = va_arg(varg, long); + long a4 = va_arg(varg, long); + long a5 = va_arg(varg, long); + long a6 = va_arg(varg, long); + va_end(varg); + + kernel_debug("==> SYSCALL %ld (%lx, %lx, %lx, %lx, %lx, %lx)\n", num, a1, a2, a3, a4, a5, a6); + + while(1); + return 0; +} + +struct pthread *__pthread_self() +{ + return 0; +} diff --git a/libc/syscalls.h b/libc/syscalls.h new file mode 100644 index 0000000..170dbd5 --- /dev/null +++ b/libc/syscalls.h @@ -0,0 +1,36 @@ +#pragma once +#include "syscall_num.h" + +#define SYSCALL_DEF(name) \ + long __syscall_##name(long num, long _a1, long _a2, long _a3, long _a4, long _a5, long _a6) + +#define _SYSCALL_INIT6(t1,n1,t2,n2,t3,n3,t4,n4,t5,n5,t6,n6) \ + (void)num; \ + t1 n1 = (t1)_a1; \ + (void)n1; \ + t2 n2 = (t2)_a2; \ + (void)n2; \ + t3 n3 = (t3)_a3; \ + (void)n3; \ + t4 n4 = (t4)_a4; \ + (void)n4; \ + t5 n5 = (t5)_a5; \ + (void)n5; \ + t6 n6 = (t6)_a6; \ + (void)n6; +#define _SYSCALL_INIT5(t1,n1,t2,n2,t3,n3,t4,n4,t5,n5) _SYSCALL_INIT6(t1,n1,t2,n2,t3,n3,t4,n4,t5,n5,long,__a6) +#define _SYSCALL_INIT4(t1,n1,t2,n2,t3,n3,t4,n4) _SYSCALL_INIT6(t1,n1,t2,n2,t3,n3,t4,n4,long,__a5,long,__a6) +#define _SYSCALL_INIT3(t1,n1,t2,n2,t3,n3) _SYSCALL_INIT6(t1,n1,t2,n2,t3,n3,long,__a4,long,__a5,long,__a6) +#define _SYSCALL_INIT2(t1,n1,t2,n2) _SYSCALL_INIT6(t1,n1,t2,n2,long,__a3,long,__a4,long,__a5,long,__a6) +#define _SYSCALL_INIT1(t1,n1) _SYSCALL_INIT6(t1,n1,long,__a2,long,__a3,long,__a4,long,__a5,long,__a6) +#define _SYSCALL_INIT0() _SYSCALL_INIT6(long,__a1,long,__a2,long,__a3,long,__a4,long,__a5,long,__a6) + +#define __SYSCALL_NARGS(a0,b0,a1,b1,a2,b2,a3,b3,a4,b4,a5,b5,a6,n,...) n +#define _SYSCALL_NARGS(...) __SYSCALL_NARGS(__VA_ARGS__,6,6,5,5,4,4,3,3,2,2,1,1,0,0) +#define __SYSCALL_CONCAT(a,b) a##b +#define _SYSCALL_CONCAT(a,b) __SYSCALL_CONCAT(a,b) +#define _SYSCALL_INIT(a,...) _SYSCALL_CONCAT(a, _SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__) +#define SYSCALL_INIT(...) _SYSCALL_INIT(_SYSCALL_INIT,__VA_ARGS__) + +long kernel_syscall(int num, ...); +void kernel_debug(char *fmt, ...); diff --git a/util/build_toolchain.sh b/util/build_toolchain.sh index 31cd0ae..3164a1f 100755 --- a/util/build_toolchain.sh +++ b/util/build_toolchain.sh @@ -18,10 +18,12 @@ musl_config="--target=${TARGET} \ --disable-shared \ --enable-debug \ CFLAGS=-O0" +musl_patchcmd="${BUILDROOT}/util/patch_musl.sh ${STASH}/musl/" musl_headers_checkfile=${SYSROOT}/usr/include/complex.h musl_headers_filename=${musl_filename} musl_headers_url=${musl_url} +musl_headers_patchcmd=${musl_patchcmd} function musl_headers_install() { local package=musl diff --git a/util/patch_musl.sh b/util/patch_musl.sh new file mode 100755 index 0000000..23b520e --- /dev/null +++ b/util/patch_musl.sh @@ -0,0 +1,84 @@ +#!/usr/bin/env bash + +set -e + +function main() +{ + readonly musl_dir=$1 + + syscall_arch=${musl_dir}/arch/x86_64/syscall_arch.h + + syscall_in=${musl_dir}/arch/x86_64/bits/syscall.h.in + + syscall_dir=${musl_dir}/src/internal/x86_64/ + + rm ${musl_dir}/src/thread/x86_64/__set_thread_area.s + rm ${syscall_dir}/syscall.s + + cat >> ${syscall_arch} << EOF +#define SYSCALL_NO_INLINE +EOF + + cat > ${syscall_dir}/syscall_1.c << EOF +#include + +#pragma weak __syscall_common +long __syscall_common(long num, ...) +{ + for(;;); +} +long __syscall_default(long num, ...) +{ for(;;); } + +typedef long (*syscall_fn)(long, ...); + +EOF + + sed -n -E 's/.*__NR_([^[:space:]]+).*/long __attribute__\(\(weak\)\) __syscall_\1\(long, ...\);/p' < ${syscall_in} >> ${syscall_dir}/syscall_1.c + + cat >> ${syscall_dir}/syscall_1.c << EOF + +syscall_fn __syscall_fns[] = { +EOF + + sed -n -E 's/.*__NR_([^[:space:]]+)[[:space:]]+([0-9]+).*/\[\2\] = __syscall_\1,/p' < ${syscall_in} >> ${syscall_dir}/syscall_1.c + + cat >> ${syscall_dir}/syscall_1.c << EOF + +}; + +EOF +cat >${syscall_dir}/syscall_2.c << EOF +#include +typedef long (*syscall_fn)(long, ...); +extern long __syscall_common(long, ...); +extern syscall_fn __syscall_fns[]; + +long __syscall(long num, ...) +{ + va_list args; + va_start(args, num); + long a1 = va_arg(args, long); + long a2 = va_arg(args, long); + long a3 = va_arg(args, long); + long a4 = va_arg(args, long); + long a5 = va_arg(args, long); + long a6 = va_arg(args, long); + va_end(args); + + if(__syscall_fns[num]) + return __syscall_fns[num](num, a1, a2, a3, a4, a5, a6); + else + return __syscall_common(num, a1, a2, a3, a4, a5, a6); +} +EOF + +cat >${musl_dir}/arch/x86_64/pthread_arch.h <