Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Please ensure the following before requesting a merge:

- [ ] I have read and agree to the repository's [CONTRIBUTING.md](https://github.com/lachlanharrisdev/virtualised-binary-obfuscation/blob/main/CONTRIBUTING.md) and [LICENSE.md](https://github.com/lachlanharrisdev/virtualised-binary-obfuscation/blob/main/LICENSE.md).
- [ ] All tests pass locally (`make`, `make test`).
- [ ] Relevant documentation has been updated (`README.md`, `docs/`).
- [ ] Relevant documentation has been updated (`README.md`, GitHub wiki(s)).
- [ ] Code follows the repository's style and formatting guidelines.
- [ ] I have added/updated relevant tests.

Expand Down
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,11 @@ dkms.conf
bin/
*.key*

riscv-gnu-toolchain-rv32i/

test/**/*
!test/**/*.c
!test/**/*.c

*.bin
*.app
*.img
95 changes: 91 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,37 @@ DIR = bin
BIN = $(DIR)/vbo
PYTHON ?= python3

SRC_COMMON = src/instructions.c src/utils.c src/hardware.c
# minimal RISCV32I VM build
SRC_COMMON = src/riscv32i.c src/utils.c
SRC_MAIN = src/main.c $(SRC_COMMON)

FLAGS = -Wall -Wextra -Werror -g -std=c11 -pedantic

# RISC-V cross toolchain (see docs/compiler.md)
RV_PREFIX ?= ~/.local/xPacks/riscv-none-elf-gcc/xpack-riscv-none-elf-gcc-14.2.0-3/bin/riscv-none-elf-
RV_GCC := $(RV_PREFIX)gcc
RV_OBJCOPY:= $(RV_PREFIX)objcopy

# Example app pipeline
OUT_DIR ?= out
EXAMPLES_DIR ?= examples
APP_SRC ?= $(EXAMPLES_DIR)/hello.c
APP_ELF := $(OUT_DIR)/app.elf
APP_BIN := $(OUT_DIR)/app.bin
APP_IMG := $(OUT_DIR)/app.img
ORIGIN ?= 0x3000

define ensure_rv_toolchain
@if ! command -v $(RV_GCC) >/dev/null 2>&1; then \
echo "[Make] Missing toolchain: $(RV_GCC). See docs/compiler.md to install and add to PATH."; \
exit 1; \
fi
@if ! command -v $(RV_OBJCOPY) >/dev/null 2>&1; then \
echo "[Make] Missing tool: $(RV_OBJCOPY). Check your riscv-none-elf toolchain installation."; \
exit 1; \
fi
endef

EMBED_IMAGE ?=
EMBED_OBJ :=
ifneq ($(strip $(EMBED_IMAGE)),)
Expand All @@ -18,7 +44,7 @@ endif

TEST_DIR = test

.PHONY: all build clean test distclean
.PHONY: all build clean test distclean app image embed run demo clean-app test-integration test-all help

all: build

Expand All @@ -34,10 +60,71 @@ clean:
rm -f $(BIN)
rm -f $(TEST_DIR)/test_utils
rm -f images/vbo_image.o
rm -rf $(OUT_DIR)

distclean: clean

test:
$(CC) $(INC) $(TEST_DIR)/test_utils.c src/utils.c src/hardware.c -o $(TEST_DIR)/test_utils $(FLAGS)
$(CC) $(INC) $(TEST_DIR)/test_utils.c src/utils.c src/riscv32i.c -o $(TEST_DIR)/test_utils $(FLAGS)
$(TEST_DIR)/test_utils
rm $(TEST_DIR)/test_utils
rm $(TEST_DIR)/test_utils

# Run both unit and integration tests (integration is skipped if toolchain is missing)
test-all: test test-integration

# --- App build pipeline ---

$(OUT_DIR):
mkdir -p $(OUT_DIR)

app: $(APP_ELF)

$(APP_ELF): $(APP_SRC) | $(OUT_DIR)
$(call ensure_rv_toolchain)
$(RV_GCC) \
-march=rv32i -mabi=ilp32 -nostdlib -ffreestanding -Os -s -fno-pic \
-Wl,--build-id=none -Wl,-Ttext=$(ORIGIN) -Wl,-e,_start \
-Iinclude -o $@ $<

$(APP_BIN): $(APP_ELF) | $(OUT_DIR)
$(RV_OBJCOPY) -O binary $< $@

image: $(APP_IMG)

$(APP_IMG): $(APP_BIN) | $(OUT_DIR)
$(PYTHON) -c 'import sys,struct; o=int(sys.argv[1],16) if str(sys.argv[1]).startswith("0x") else int(sys.argv[1]); open(sys.argv[2],"wb").write(struct.pack(">I",o)+open(sys.argv[3],"rb").read())' \
$(ORIGIN) $@ $<

# Embed convenience: uses APP_IMG if EMBED_IMAGE not provided
embed: image
$(MAKE) build EMBED_IMAGE=$(APP_IMG)

run: build image
$(BIN) $(APP_IMG)

demo: embed run

clean-app:
rm -rf $(OUT_DIR)

# Integration test (optional): requires toolchain, builds hello and checks output
test-integration: build
@if ! command -v $(RV_GCC) >/dev/null 2>&1 || ! command -v $(RV_OBJCOPY) >/dev/null 2>&1; then \
echo "[Test] Skipping integration test (toolchain not found). See docs/compiler.md"; \
exit 0; \
fi
@$(MAKE) --no-print-directory image
@echo "[Test] Running integration test (hello)"
@out=$$($(BIN) $(APP_IMG)); echo "$$out" | grep -q "Hello from RV32I VM" && echo "[Test] OK" || (echo "[Test] FAIL"; exit 1)

help:
@echo "Targets:"
@echo " build - Build the VM"
@echo " app - Build example app (set APP_SRC=...)"
@echo " image - Make flat image with origin header from app"
@echo " embed - Embed image and rebuild VM"
@echo " run - Run VM with built image"
@echo " demo - Build+embed+run example app end-to-end"
@echo " test - Run unit tests"
@echo " test-all - Run unit + integration tests (if toolchain available)"
@echo " clean / distclean- Remove build artifacts"
14 changes: 0 additions & 14 deletions docs/compiler.md

This file was deleted.

16 changes: 0 additions & 16 deletions docs/isa.md

This file was deleted.

14 changes: 0 additions & 14 deletions docs/obfuscation.md

This file was deleted.

65 changes: 0 additions & 65 deletions docs/vm.md

This file was deleted.

14 changes: 14 additions & 0 deletions examples/hello.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include <stdint.h>
#include "rv32_syscalls.h"

static const char msg[] = "Hello from RV32I VM\n";

int main(void) {
sys_write(1, msg, (uint32_t)(sizeof(msg) - 1));
return 0;
}

extern int main(void);
__attribute__((noreturn)) void _start(void) {
sys_exit(main());
}
Loading