From e6237cc06e562f62a957bdd0474b4aa7aaebf500 Mon Sep 17 00:00:00 2001 From: Christoph Urlacher Date: Thu, 5 Mar 2026 19:16:03 +0100 Subject: [PATCH] include + update old linux targets/host.c --- .gitignore | 2 + Makefile | 5 +- examples/arch/bochs.mk | 71 ++++++++++++++++++---- examples/arch/bochs/bochsrc-host.txt | 1 - examples/arch/bochs/startup.s | 69 ++++++++++++++++++--- examples/arch/linux.mk | 84 -------------------------- examples/embed/host-linux.c | 89 ++++++++++++++++++++++++++++ examples/embed/host.c | 24 ++++++-- examples/linker.ld | 2 +- wasm-base.dockerfile | 19 +++--- 10 files changed, 241 insertions(+), 125 deletions(-) delete mode 100644 examples/arch/linux.mk create mode 100644 examples/embed/host-linux.c diff --git a/.gitignore b/.gitignore index 471063e..087a8e2 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ examples/build-*/ +/examples/bochslog.txt +/bochslog.txt diff --git a/Makefile b/Makefile index 7ecf78f..cab860a 100644 --- a/Makefile +++ b/Makefile @@ -7,8 +7,5 @@ run: run-external: docker run --rm -it -v "./examples:/home/ubuntu/examples" gitea.vps.chriphost.de/christoph/wasm-base:latest /usr/bin/fish -bochs: - bochs -f ./examples/arch/bochs/bochsrc-docker.txt -q - bochs-host: - nix shell nixpkgs#bochs --command sh -c "bochs -f ./examples/arch/bochs/bochsrc-host.txt -q" + nix shell nixpkgs#bochs --command sh -c "bochs -q -f ./examples/arch/bochs/bochsrc-host.txt -q" diff --git a/examples/arch/bochs.mk b/examples/arch/bochs.mk index 900ec33..041045f 100644 --- a/examples/arch/bochs.mk +++ b/examples/arch/bochs.mk @@ -16,17 +16,25 @@ WASI_CFLAGS := \ # WASM -> Baremetal WAMR := /opt/wamr -IWASM_LIB := /opt/wamr-libiwasm -CC := /opt/crosscompiler/bin/i686-elf-gcc -# NOTE: When compiling I get "error: bp cannot be used in ‘asm’ here" -# I could remove "ebp" from the clobber list (ARCH_ASM_CLOBBER_ALL) or + +WAMRC := /opt/wamr-wamrc/wamrc +WAMRCFLAGS := \ + --target=i386 \ + --cpu=generic +XXD := busybox xxd + +# NOTE: make build-sum: "error: bp cannot be used in ‘asm’ here" +# could remove "ebp" from the clobber list (ARCH_ASM_CLOBBER_ALL) or # use the -fomit-frame-pointer flag to tell gcc it shouldn't rely on ebp for enter/leave... +CC := /opt/crosscompiler/bin/i686-elf-gcc CFLAGS := \ -I. \ -O0 \ -m32 \ -ffunction-sections \ - -fomit-frame-pointer + -fomit-frame-pointer \ + -ggdb +IWASM_LIB := /opt/wamr-libiwasm # Baremetal LDFLAGS = \ -Wl,-T linker.ld \ $^ \ @@ -44,8 +52,26 @@ INCL := \ -I${WAMR}/core/shared/utils \ -I${WAMR}/core/shared/platform/baremetal \ -I/opt/crosscompiler/i686-elf/include -WAMRC := /opt/wamr-wamrc/wamrc -XXD := busybox xxd + +CC_LINUX := gcc +CFLAGS_LINUX := \ + -I. \ + -O0 \ + -m32 \ + -ffunction-sections \ + -ggdb +IWASM_LIB_LINUX := /opt/wamr-libiwasm-linux +LDFLAGS_LINUX = \ + $^ \ + -m32 \ + -Wl,-rpath,${IWASM_LIB_LINUX} \ + -L${IWASM_LIB_LINUX} \ + -liwasm \ + -lm +INCL_LINUX := \ + -I${WAMR}/core/iwasm/include \ + -I${WAMR}/core/shared/utils \ + -I${WAMR}/core/shared/platform/linux ################################################################ # C -> WASM @@ -65,9 +91,9 @@ ${BUILD_DIR}/%/module.wasm: %.c # ${CC} ${LDFLAGS} -o $@ ################################################################ -# WASM -> AOT -> Loaded by Runtime +# WASM -> AOT -> Loaded by Runtime (FAIL) ${BUILD_DIR}/%/module.aot: ${BUILD_DIR}/%/module.wasm - ${WAMRC} -o $@ $< + ${WAMRC} ${WAMRCFLAGS} -o $@ $< ${BUILD_DIR}/%/module_wasm.c: ${BUILD_DIR}/%/module.aot ${XXD} -i $< > $@ @@ -90,6 +116,20 @@ ${BUILD_DIR}/syscalls.o: syscalls.c ${BUILD_DIR}/%/system.elf: ${BUILD_DIR}/%/system.o ${BUILD_DIR}/syscalls.o ${BUILD_DIR}/startup.o ${CC} ${LDFLAGS} -o $@ +################################################################ +# WASM -> AOT -> Loaded by Runtime (Host/Linux) +${BUILD_DIR}/%/system-linux.o: ${BUILD_DIR}/%/module_wasm.c + cp embed/host-linux.c ${BUILD_DIR}/$*/module_host-linux.c + sed -i \ + -e "s/__WASM_ARRAY_FILE__/module_wasm.c/g" \ + -e "s/__WASM_ARRAY__/build_bochs_$*_module_aot/g" \ + -e "s/__WASM_ARRAY_LEN__/build_bochs_$*_module_aot_len/g" \ + ${BUILD_DIR}/$*/module_host-linux.c + ${CC_LINUX} ${CFLAGS_LINUX} ${INCL_LINUX} -c ${BUILD_DIR}/$*/module_host-linux.c -o $@ + +${BUILD_DIR}/%/system-linux.elf: ${BUILD_DIR}/%/system-linux.o + ${CC_LINUX} ${LDFLAGS_LINUX} -o $@ + ################################################################ # Bochs ${BUILD_DIR}/%/system.iso: ${BUILD_DIR}/%/system.elf @@ -167,6 +207,17 @@ build-$1: ${BUILD_DIR}/$1/system.iso trace-$1: ${BUILD_DIR}/$1/trace.pb objdump-$1: - objdump --disassemble --disassembler-options intel --disassembler-color=on --source ${BUILD_DIR}/$1/system.elf + objdump --disassemble --disassembler-options intel --disassembler-color=off --source ${BUILD_DIR}/$1/system.elf | less + +linux-build-$1: ${BUILD_DIR}/$1/system-linux.elf + +linux-run-$1: ${BUILD_DIR}/$1/system-linux.elf + ${BUILD_DIR}/$1/system-linux.elf + +linux-gdb-$1: ${BUILD_DIR}/$1/system-linux.elf + gdb --tui ${BUILD_DIR}/$1/system-linux.elf + +bochs-run-$1: ${BUILD_DIR}/$1/system.iso + bochs -q -f arch/bochs/bochsrc-docker.txt endef diff --git a/examples/arch/bochs/bochsrc-host.txt b/examples/arch/bochs/bochsrc-host.txt index 205d1d0..9bba12c 100644 --- a/examples/arch/bochs/bochsrc-host.txt +++ b/examples/arch/bochs/bochsrc-host.txt @@ -4,7 +4,6 @@ romimage: file="/home/christoph/Notes/TU/MastersThesis/3 Wasm/examples/arch/boch vgaromimage: file="/home/christoph/Notes/TU/MastersThesis/3 Wasm/examples/arch/bochs/vgabios.bin" ata0-master: type=cdrom, path="/home/christoph/Notes/TU/MastersThesis/3 Wasm/examples/build-bochs/sum/system.iso", status=inserted boot: cdrom -log: bochslog.txt clock: sync=realtime, time0=local cpu: count=1, ips=1000000 sound: driver=dummy diff --git a/examples/arch/bochs/startup.s b/examples/arch/bochs/startup.s index fdd4f8d..2682331 100644 --- a/examples/arch/bochs/startup.s +++ b/examples/arch/bochs/startup.s @@ -13,20 +13,41 @@ # checksum: -(magic+flags) .long -(0x1BADB002 + 0x3) - - # the initial kernel stack .section .kernel_stack .global os_stack .size os_stack, 4096 + +# NOTE: New Start + +# .section .gdt +# gdt_start: +# .quad 0x0000000000000000 # null descriptor +# .quad 0x00cf9a000000ffff # code segment descriptor: base=0, limit=4GB, 32-bit code +# .quad 0x00cf92000000ffff # data segment descriptor: base=0, limit=4GB, 32-bit data +# gdt_end: +# +# gdt_descriptor: +# .word gdt_end - gdt_start - 1 # limit +# .long gdt_start # base +# +# .section .idt +# idt_table: +# .space 256*8 # 256 entries x 8 bytes each +# idt_descriptor: +# .word 256*8-1 # limit +# .long idt_table # base + +# NOTE: New End + #.Lstack_bottom: os_stack: -.byte 0 -#.skip 16384 # 16 KiB -.skip 4094 # 4 KiB -.byte 0 -.Lstack_top: - + .byte 0 + .skip 65565 # 64 KiB + # .skip 16384 # 16 KiB + # .skip 4094 # 4 KiB + .byte 0 + .Lstack_top: # The linker script specifies _start as the entry point to the kernel and the @@ -36,7 +57,9 @@ os_stack: .global _start .type _start, @function _start: - # Welcome to kernel mode! +# NOTE: Old Start + + # Welcome to kernel mode! # To set up a stack, we simply set the esp register to point to the top of # our stack (as it grows downwards). movl $.Lstack_top, %esp @@ -54,6 +77,34 @@ _start: .Lhang: jmp .Lhang +# NOTE: Old End + +# NOTE: New Start + +# cli +# +# lgdt gdt_descriptor # GDT +# lidt idt_descriptor # IDT Stub +# +# # set up segment registers (flat 32-bit) +# movw $0x10, %ax +# movw %ax, %ds +# movw %ax, %es +# movw %ax, %fs +# movw %ax, %gs +# movw %ax, %ss +# movl $.Lstack_top, %esp # set stack +# +# # call main C function +# call os_main +# +# cli +# hlt +# .Lhang: +# jmp .Lhang + +# NOTE: New End + # Set the size of the _start symbol to the current location '.' minus its start. # This is useful when debugging or when you implement call tracing. .size _start, . - _start diff --git a/examples/arch/linux.mk b/examples/arch/linux.mk deleted file mode 100644 index 3c1c027..0000000 --- a/examples/arch/linux.mk +++ /dev/null @@ -1,84 +0,0 @@ -# C -> WASM -WASI_ROOT := /opt/wasi-sdk -WASI_CC := ${WASI_ROOT}/bin/clang -WASI_CFLAGS := --target=wasm64 \ - --sysroot=${WASI_ROOT}/share/wasi-sysroot \ - -z stack-size=4096 \ - -O0 -g -nostdlib \ - -Wl,--no-entry \ - -Wl,--initial-memory=65536 \ - -Wl,--export-all \ - -Wl,--export=__heap_base \ - -Wl,--export=__data_end - -# WASM -> Baremetal -WAMR := /opt/wamr -IWASM_LIB := /opt/wamr-libiwasm-64 -CC := gcc -# NOTE: When compiling I get "error: bp cannot be used in ‘asm’ here" -# I could remove "ebp" from the clobber list (ARCH_ASM_CLOBBER_ALL) or -# use the -fomit-frame-pointer flag to tell gcc it shouldn't rely on ebp for enter/leave... -CFLAGS := -I. -O0 -g -ffunction-sections -std=c11 -fomit-frame-pointer -LDFLAGS = $^ -Wl,--build-id=none -static -nostdlib \ - -Wl,-rpath,${IWASM_LIB} -L${IWASM_LIB} -liwasm -lgcc -INCL := -I${WAMR}/core/iwasm/include \ - -I${WAMR}/core/shared/utils \ - -I${WAMR}/core/shared/platform/baremetal -WAMRC := /opt/wamr-wamrc/wamrc -WAMRCFLAGS := --target=i386 --format=object -XXD := busybox xxd - -################################################################ -# C -> WASM -${BUILD_DIR}/%/module.wasm: %.c - mkdir -p $(shell dirname $@) - ${WASI_CC} ${WASI_CFLAGS} $< -o $@ - -################################################################ -# WASM -> Native Object File -# ${BUILD_DIR}/%/system.o: ${BUILD_DIR}/%/module.wasm -# ${WAMRC} ${WAMRCFLAGS} -o ${BUILD_DIR}/$*/system.o ${BUILD_DIR}/$*/module.wasm -# -# ${BUILD_DIR}/startup.o: arch/bochs/startup.s -# ${CC} $< ${CFLAGS} -c -o $@ -# -# ${BUILD_DIR}/%/system.elf: ${BUILD_DIR}/%/system.o ${BUILD_DIR}/startup.o -# ${CC} ${LDFLAGS} -o $@ - -################################################################ -# WASM -> AOT -> Loaded by Runtime -${BUILD_DIR}/%/module.aot: ${BUILD_DIR}/%/module.wasm - ${WAMRC} -o $@ $< - -${BUILD_DIR}/%/module_wasm.c: ${BUILD_DIR}/%/module.aot - ${XXD} -i $< > $@ - -${BUILD_DIR}/%/system.o: ${BUILD_DIR}/%/module_wasm.c - cp embed/host.c ${BUILD_DIR}/$*/module_host.c - sed -i \ - -e "s/__WASM_ARRAY_FILE__/module_wasm.c/g" \ - -e "s/__WASM_ARRAY__/build_linux_$*_module_aot/g" \ - -e "s/__WASM_ARRAY_LEN__/build_linux_$*_module_aot_len/g" \ - ${BUILD_DIR}/$*/module_host.c - ${CC} ${CFLAGS} ${INCL} -c ${BUILD_DIR}/$*/module_host.c -o $@ - -${BUILD_DIR}/startup.o: arch/bochs/startup.s - ${CC} $< ${CFLAGS} -c -o $@ - -${BUILD_DIR}/%/system.elf: ${BUILD_DIR}/%/system.o ${BUILD_DIR}/startup.o - ${CC} ${LDFLAGS} -o $@ - -define arch-make-targets - -build-$1: ${BUILD_DIR}/$1/system.elf - -gdb-$1: - gdb --tui ${BUILD_DIR}/$1/system.elf - -valgrind-$1: - valgrind ${BUILD_DIR}/$1/system.elf - -objdump-$1: - objdump --disassemble --start-address=0x401000 --stop-address=0x401200 --disassembler-options intel --disassembler-color=on --source ${BUILD_DIR}/$1/system.elf - -endef diff --git a/examples/embed/host-linux.c b/examples/embed/host-linux.c new file mode 100644 index 0000000..c463187 --- /dev/null +++ b/examples/embed/host-linux.c @@ -0,0 +1,89 @@ +// https://github.com/bytecodealliance/wasm-micro-runtime/blob/WAMR-2.4.4/doc/embed_wamr.md + +#include "lib.c" + +#include "bh_platform.h" +#include "wasm_export.h" + +#include "__WASM_ARRAY_FILE__" +#include + +#define STACK_SIZE (4 * 1024) +#define HEAP_SIZE STACK_SIZE +#define RUNTIME_POOL_SIZE 4 * STACK_SIZE + +// TODO: Set this up so the lsp actually finds the includes... + +// MAIN() { +int main(int argc, char *argv[]) { + char error_buf[128]; + wasm_module_t module; + wasm_module_inst_t module_inst; + wasm_function_inst_t func; + wasm_exec_env_t exec_env; + + /* initialize the wasm runtime */ + static char global_heap_buf[RUNTIME_POOL_SIZE]; + static RuntimeInitArgs init_args; + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + // init_args.mem_alloc_type = Alloc_With_System_Allocator; + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + init_args.max_thread_num = 1; + if (!wasm_runtime_full_init(&init_args)) { + return 1; + } + + /* parse the WASM file from buffer and create a WASM module */ + module = wasm_runtime_load(__WASM_ARRAY__, __WASM_ARRAY_LEN__, error_buf, + sizeof(error_buf)); + + if (!module) { + printf("Load failed: %s\n", error_buf); + return 1; + } + + /* create an instance of the WASM module (WASM linear memory is ready) */ + module_inst = wasm_runtime_instantiate(module, STACK_SIZE, HEAP_SIZE, + error_buf, sizeof(error_buf)); + + if (!module_inst) { + printf("Inst failed: %s\n", error_buf); + return 1; + } + + /* lookup a WASM function by its name, the function signature can NULL here */ + func = wasm_runtime_lookup_function(module_inst, "wasm_module"); + + /* create an execution environment to execute arbitrary WASM functions */ + exec_env = wasm_runtime_create_exec_env(module_inst, STACK_SIZE); + + /* arguments are always transferred in 32-bit element */ + uint32 args[1]; + + /* call an arbitrary WASM function */ + // MARKER(start_trace); + if (!wasm_runtime_call_wasm(exec_env, func, 0, args)) { + /* function wasn't called correctly */ + printf("Failed to call function 'wasm_module'!\n"); + } + // MARKER(stop_trace); + + printf("Sum: %d\n", args[0]); + + /* the return value is stored in args[0] */ + if (args[0] == 100) { + // MARKER(ok_marker); + } else { + // MARKER(fail_marker); + } + + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(module_inst); + wasm_runtime_unload(module); + wasm_runtime_destroy(); + + return 0; +} diff --git a/examples/embed/host.c b/examples/embed/host.c index e726fac..037bf29 100644 --- a/examples/embed/host.c +++ b/examples/embed/host.c @@ -8,7 +8,8 @@ #include "__WASM_ARRAY_FILE__" #define STACK_SIZE (4 * 1024) -#define HEAP_SIZE (4 * 1024) +#define HEAP_SIZE STACK_SIZE +#define RUNTIME_POOL_SIZE 4 * STACK_SIZE // TODO: Set this up so the lsp actually finds the includes... @@ -20,10 +21,11 @@ MAIN() { wasm_exec_env_t exec_env; /* initialize the wasm runtime */ - static char global_heap_buf[HEAP_SIZE]; - RuntimeInitArgs init_args; + static char global_heap_buf[RUNTIME_POOL_SIZE]; + static RuntimeInitArgs init_args; memset(&init_args, 0, sizeof(RuntimeInitArgs)); + // init_args.mem_alloc_type = Alloc_With_System_Allocator; init_args.mem_alloc_type = Alloc_With_Pool; init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); @@ -36,10 +38,20 @@ MAIN() { module = wasm_runtime_load(__WASM_ARRAY__, __WASM_ARRAY_LEN__, error_buf, sizeof(error_buf)); + if (!module) { + // printf("Load failed: %s\n", error_buf); + return; + } + /* create an instance of the WASM module (WASM linear memory is ready) */ module_inst = wasm_runtime_instantiate(module, STACK_SIZE, HEAP_SIZE, error_buf, sizeof(error_buf)); + if (!module_inst) { + // printf("Inst failed: %s\n", error_buf); + return; + } + /* lookup a WASM function by its name, the function signature can NULL here */ func = wasm_runtime_lookup_function(module_inst, "wasm_module"); @@ -53,11 +65,11 @@ MAIN() { MARKER(start_trace); if (!wasm_runtime_call_wasm(exec_env, func, 0, args)) { /* function wasn't called correctly */ - POSIX_PRINTF("Failed to call function 'wasm_module'!\n"); + // printf("Failed to call function 'wasm_module'!\n"); } MARKER(stop_trace); - POSIX_PRINTF("Sum: %d\n!", args[0]); + // printf("Sum: %d\n", args[0]); /* the return value is stored in args[0] */ if (args[0] == 100) { @@ -70,4 +82,6 @@ MAIN() { wasm_runtime_deinstantiate(module_inst); wasm_runtime_unload(module); wasm_runtime_destroy(); + + return; } diff --git a/examples/linker.ld b/examples/linker.ld index 6ce8d07..0dd893c 100644 --- a/examples/linker.ld +++ b/examples/linker.ld @@ -18,7 +18,7 @@ SECTIONS { /* Code and readonly data */ .text : { /* fill gaps with int3 opcode to detect invalid jumps */ - /* TODO: This crashes bochs */ + /* TODO: Crashes */ FILL(0xcc) /* multiboot header */ diff --git a/wasm-base.dockerfile b/wasm-base.dockerfile index c0719a6..eb7c4df 100644 --- a/wasm-base.dockerfile +++ b/wasm-base.dockerfile @@ -47,8 +47,7 @@ RUN mkdir gcc-build && cd gcc-build \ # && PATH="$CROSSPREFIX/bin:$PATH" make all-target-libstdc++-v3 -j$(nproc) \ # && PATH="$CROSSPREFIX/bin:$PATH" make install-target-libstdc++-v3 -# Build newlib - it seems like because I use the same gcc prefix -# I don't even need to specify it as an include when building? +# Build newlib in the gcc prefix - don't need to specify include paths ARG NEWLIBVERSION=4.1.0 WORKDIR / RUN wget ftp://sourceware.org/pub/newlib/newlib-$NEWLIBVERSION.tar.gz \ @@ -85,10 +84,6 @@ RUN apt-get update \ wget \ && apt-get clean -# TODO: Can't find pthread on X86_32 -# RUN ln -s /usr/lib/x86_64-linux-gnu/libpthread.so.0 /usr/lib/x86_64-linux-gnu/libpthread.so -# RUN ln -s /usr/lib32/libpthread.so.0 /usr/lib32/libpthread.so - RUN python3 -m pip config set global.break-system-packages true # Clone WAMR @@ -185,12 +180,13 @@ RUN mkdir build_libiwasm && cd build_libiwasm \ .. \ && make -j$(nproc) +# Build WAMR libiwasm for the host system WORKDIR /wamrlib -RUN mkdir build_libiwasm_64 && cd build_libiwasm_64 \ +RUN mkdir build_libiwasm_linux && cd build_libiwasm_linux \ && cmake \ - -DWAMR_BUILD_PLATFORM=baremetal \ - -DWAMR_BUILD_TARGET=X86_64 \ - -DWAMR_BUILD_AOT=0 \ + -DWAMR_BUILD_PLATFORM=linux \ + -DWAMR_BUILD_TARGET=X86_32 \ + -DWAMR_BUILD_AOT=1 \ -DWAMR_BUILD_WAMR_COMPILER=0 \ -DWAMR_BUILD_INTERP=1 \ -DWAMR_BUILD_FAST_INTERP=0 \ @@ -225,6 +221,7 @@ RUN apt-get update \ xorriso \ grub-pc-bin \ bochs \ + less \ && apt-get clean COPY --from=compiler-builder /opt/crosscompiler /opt/crosscompiler @@ -235,7 +232,7 @@ RUN ln -sf /opt/wamr/product-mini/platforms/linux/build_iwasm /opt/wamr-iwasm \ && ln -sf /opt/wamr/wamr-compiler/build_wamrc /opt/wamr-wamrc \ && ln -sf /opt/wamr/wamr-compiler/build_libvmlib /opt/wamr-libvmlib \ && ln -sf /opt/wamr/build_libiwasm /opt/wamr-libiwasm \ - && ln -sf /opt/wamr/build_libiwasm_64 /opt/wamr-libiwasm-64 + && ln -sf /opt/wamr/build_libiwasm_linux /opt/wamr-libiwasm-linux COPY ./examples /home/ubuntu/examples WORKDIR /home/ubuntu/examples