BUILD_DIR := "build" # Load environment variables set by "nix develop"-shell FAIL_SHARE := env("FAIL_SHARE") WASI_ROOT := env("WASI_ROOT") WAMR_ROOT := env("WAMR_ROOT") LIBIWASM_DEBUG := env("LIBIWASM_DEBUG") LIBIWASM_RELEASE := env("LIBIWASM_RELEASE") CROSS_CC := env("CROSSCC") CROSS_CXX := env("CROSSCXX") # C -> WASM WASI_CC := f"{{WASI_ROOT}}/bin/clang" WASI_CFLAGS := "\ --target=wasm32 \ --sysroot={{WASI_ROOT}}/share/wasi-sysroot \ -z stack-size=4096 \ -O0 \ -nostdlib \ -Wl,--no-entry \ -Wl,--export-all \ -Wl,--no-gc-sections \ -Wl,--initial-memory=65536 \ -Wl,--export=__heap_base \ -Wl,--export=__data_end \ " # WASM -> AOT WAMRC := "wamrc" WAMRCFLAGS := "\ --target=i386 \ --cpu=generic \ --opt-level=0 \ " XXD := "xxd" # Load AOT from WAMR CROSS_CFLAGS := "\ -I./targets/wasm-host \ -O2 \ -m32 \ -ffunction-sections \ -fdata-sections \ -ffreestanding \ -fomit-frame-pointer \ -ggdb \ " CROSS_LDFLAGS := f"\ -Wl,--build-id=none \ -static \ -nostdlib \ -m32 \ -L{{LIBIWASM_RELEASE}} \ -liwasm \ -lc \ -lgcc \ -lm \ " CROSS_INCLUDES := f"\ -I{{WAMR_ROOT}}/core/iwasm/include \ -I{{WAMR_ROOT}}/core/shared/utils \ -I{{WAMR_ROOT}}/core/shared/platform/baremetal \ " # Build recipes [default] [private] list: @just --list --unsorted [private] create-build-dir module: mkdir -p {{ BUILD_DIR }}-{{ module }} [doc("Delete the build directory")] clean module: rm -rf {{ BUILD_DIR }}-{{ module }} [doc("C -> WASM: Compile a C function to a WASM module using WASI-SDK")] [group("build")] build-wasm-module module: (create-build-dir module) {{ WASI_CC }} {{ WASI_CFLAGS }} targets/wasm-module/{{ module }}.c -o {{ BUILD_DIR }}-{{ module }}/wasm_module.wasm [doc("WASM -> AOT: Compile a WASM module ahead-of-time using WAMR")] [group("build")] build-wasm-aot module: (build-wasm-module module) {{ WAMRC }} {{ WAMRCFLAGS }} -o {{ BUILD_DIR }}-{{ module }}/wasm_module.aot {{ BUILD_DIR }}-{{ module }}/wasm_module.wasm [doc("AOT -> C-Array: Dump a WASM module compiled ahead-of-time to a binary array")] [group("build")] build-wasm-aot-array module: (build-wasm-aot module) {{ XXD }} -i {{ BUILD_DIR }}-{{ module }}/wasm_module.aot > {{ BUILD_DIR }}-{{ module }}/wasm_module_array.c [doc("Compile C-Host: The host uses WAMR to load the AOT module")] [group("build")] build-wasm-host module target="fail": (build-wasm-aot-array module) cp targets/wasm-host/{{ target }}.c {{ BUILD_DIR }}-{{ module }}/module_host.c sed -i \ -e "s/__WASM_ARRAY_FILE__/wasm_module_array.c/g" \ -e "s/__WASM_ARRAY__/build_{{ module }}_wasm_module_aot/g" \ -e "s/__WASM_ARRAY_LEN__/build_{{ module }}_wasm_module_aot_len/g" \ {{ BUILD_DIR }}-{{ module }}/module_host.c {{ CROSS_CC }} {{ CROSS_CFLAGS }} {{ CROSS_INCLUDES }} \ -c {{ BUILD_DIR }}-{{ module }}/module_host.c \ -o {{ BUILD_DIR }}-{{ module }}/system.o [doc("Compile bootloader")] [group("build")] build-system-startup module: {{ CROSS_CC }} targets/startup.s {{ CROSS_CFLAGS }} -c -o {{ BUILD_DIR }}-{{ module }}/startup.o [doc("Compile newlib syscall stubs")] [group("build")] build-system-syscalls module: {{ CROSS_CC }} targets/syscalls.c {{ CROSS_CFLAGS }} -c -o {{ BUILD_DIR }}-{{ module }}/syscalls.o [doc("Link C-Host, syscall stubs and bootloader")] [group("build")] build-system module target="fail": (build-wasm-host module target) (build-system-syscalls module) (build-system-startup module) {{ CROSS_CC }} -Wl,-T targets/linker.ld \ {{ BUILD_DIR }}-{{ module }}/system.o \ {{ BUILD_DIR }}-{{ module }}/syscalls.o \ {{ BUILD_DIR }}-{{ module }}/startup.o \ {{ CROSS_LDFLAGS }} -o {{ BUILD_DIR }}-{{ module }}/system.elf [doc("Create bootdisk")] [group("build")] build-iso module target="fail": (build-system module target) mkdir -p {{ BUILD_DIR }}-{{ module }}/grub/boot/grub cp targets/grub.cfg {{ BUILD_DIR }}-{{ module }}/grub/boot/grub/ cp {{ BUILD_DIR }}-{{ module }}/system.elf {{ BUILD_DIR }}-{{ module }}/grub/boot/ grub-mkrescue -o {{ BUILD_DIR }}-{{ module }}/system.iso {{ BUILD_DIR }}-{{ module }}/grub # FAIL* recipes BOCHS_RUNNER := "bochs-experiment-runner.py" FAIL_TRACE := "fail-x86-tracing" FAIL_DUMP := "dump-trace" FAIL_IMPORT := "import-trace --database-option-file ./db.conf" FAIL_PRUNE := "prune-trace --database-option-file ./db.conf" FAIL_SERVER := "generic-experiment-server --database-option-file ./db.conf" FAIL_INJECT := "generic-experiment-client" RESULT_BROWSER := "resultbrowser.py -c ./db.conf" [doc("Start MySQL to receive FAIL* trace/campaign results")] [group("fail")] start-db: docker compose up [doc("Stop MySQL")] [group("fail")] stop-db: docker compose down [doc("Trace a golden run using FAIL*")] [group("fail")] trace module: {{ BOCHS_RUNNER }} \ -V {{ FAIL_SHARE }}/vgabios.bin \ -b {{ FAIL_SHARE }}/BIOS-bochs-latest \ -1 \ -f {{ FAIL_TRACE }} \ -e {{ BUILD_DIR }}-{{ module }}/system.elf \ -i {{ BUILD_DIR }}-{{ module }}/system.iso \ -- \ -Wf,--start-symbol=start_trace \ -Wf,--save-symbol=start_trace \ -Wf,--end-symbol=stop_trace \ -Wf,--state-file={{ BUILD_DIR }}-{{ module }}/state \ -Wf,--trace-file={{ BUILD_DIR }}-{{ module }}/trace.pb \ -Wf,--elf-file={{ BUILD_DIR }}-{{ module }}/system.elf @echo "Next step: \"just import {{ module }}\"" [doc("Import a FAIL* golden run trace")] [group("fail")] import module: {{ FAIL_IMPORT }} -t {{ BUILD_DIR }}-{{ module }}/trace.pb -i MemoryImporter \ -e {{ BUILD_DIR }}-{{ module }}/system.elf -v {{ module }} -b mem {{ FAIL_IMPORT }} -t {{ BUILD_DIR }}-{{ module }}/trace.pb -i RegisterImporter \ -e {{ BUILD_DIR }}-{{ module }}/system.elf -v {{ module }} -b regs --flags {{ FAIL_IMPORT }} -t {{ BUILD_DIR }}-{{ module }}/trace.pb -i RegisterImporter \ -e {{ BUILD_DIR }}-{{ module }}/system.elf -v {{ module }} -b ip --no-gp --ip # TODO: Failed to decode DWARF data - wrong libdwarf version? # # {{ FAIL_IMPORT }} -t {{ BUILD_DIR }}-{{ module }}/trace.pb -i ElfImporter --objdump objdump \ # -e {{ BUILD_DIR }}-{{ module }}/system.elf -v {{ module }} -b ip # {{ FAIL_IMPORT }} -t {{ BUILD_DIR }}-{{ module }}/trace.pb -i ElfImporter --objdump objdump \ # -e {{ BUILD_DIR }}-{{ module }}/system.elf -v {{ module }} -b mem # {{ FAIL_IMPORT }} -t {{ BUILD_DIR }}-{{ module }}/trace.pb -i ElfImporter --objdump objdump \ # -e {{ BUILD_DIR }}-{{ module }}/system.elf -v {{ module }} -b regs # {{ FAIL_IMPORT }} -t {{ BUILD_DIR }}-{{ module }}/trace.pb -i ElfImporter --objdump objdump \ # -e {{ BUILD_DIR }}-{{ module }}/system.elf -v {{ module }} -b ip --sources # {{ FAIL_IMPORT }} -t {{ BUILD_DIR }}-{{ module }}/trace.pb -i ElfImporter --objdump objdump \ # -e {{ BUILD_DIR }}-{{ module }}/system.elf -v {{ module }} -b mem --sources # {{ FAIL_IMPORT }} -t {{ BUILD_DIR }}-{{ module }}/trace.pb -i ElfImporter --objdump objdump \ # -e {{ BUILD_DIR }}-{{ module }}/system.elf -v {{ module }} -b regs --sources {{ FAIL_PRUNE }} -v {{ module }} -b %% --overwrite @echo "Next step: \"just server {{ module }}\"" [doc("Start the FAIL* campaign server")] [group("fail")] server module: {{ FAIL_SERVER }} -v {{ module }} -b % --inject-single-bit --inject-registers & @echo "Next step: \"just client {{ module }}\"" [doc("Start a FAIL* campaign client")] [group("fail")] client module: {{ BOCHS_RUNNER }} \ -V {{ FAIL_SHARE }}/vgabios.bin \ -b {{ FAIL_SHARE }}/BIOS-bochs-latest \ -f {{ FAIL_INJECT }} \ -e {{ BUILD_DIR }}-{{ module }}/system.elf \ -i {{ BUILD_DIR }}-{{ module }}/system.iso \ -j {{ num_cpus() }} \ -- \ -Wf,--state-dir={{ BUILD_DIR }}-{{ module }}/state \ -Wf,--trap \ -Wf,--timeout=500000 \ -Wf,--ok-marker=ok_marker \ -Wf,--fail-marker=fail_marker \ 2>/dev/null | grep -B 2 -A 8 'INJECT' @echo "Next step: \"just result {{ module }}\" or \"just resultbrowser\"" [doc("Query FAIL* marker statistics from the database")] [group("fail")] result module: @echo "select variant, benchmark, resulttype, sum(t.time2 - t.time1 + 1) as faults \ FROM variant v \ JOIN trace t ON v.id = t.variant_id \ JOIN fspgroup g ON g.variant_id = t.variant_id AND g.instr2 = t.instr2 AND g.data_address = t.data_address \ JOIN result_GenericExperimentMessage r ON r.pilot_id = g.pilot_id \ JOIN fsppilot p ON r.pilot_id = p.id \ WHERE v.variant = \"{{ module }}\" \ GROUP BY v.id, resulttype \ ORDER BY variant, benchmark, resulttype;" | mariadb --defaults-file=./db.conf -t [doc("Start the FAIL* resultbrowser")] [group("fail")] resultbrowser: {{ RESULT_BROWSER }} --host=0.0.0.0 --port=5000