Hi,
On Fri, 10 Jul 2026 01:04:37 +0800, Ziyang Zhang wrote:
Document the dlcall plugin under Example Plugins: what it does, the trusted-
guests and guest_base == 0 constraints, how to load it, and a pointer to
Lorelei, one end-to-end userspace implementation, for the toolchain and a
runnable example.
Patch 2/2 walks through the hello example one step at a time. If you
would rather not run those steps by hand, the self-contained Makefile
below does the whole thing in one command: it downloads the devkit,
writes the sources, and builds the thunk tree from patch 2/2. After
that,
make QEMU=<your qemu-x86_64> PLUGIN=<contrib/plugins/libdlcall.so> run
runs the guest both ways and prints hello from guest then hello from
host.
It only needs wget or curl to fetch the devkit from the GitHub release,
plus a qemu-x86_64 built from this series for the run step. Drop it in
an empty directory and run make.
# ---- Makefile ----
# One-click Lorelei hello quickstart. From nothing, this Makefile
downloads the
# devkit, writes the example sources, and builds the thunk tree from the
# walkthrough. Everything lands under this directory.
#
# make download the devkit if needed, then build the tree
# make tree print the resulting directory tree
# make run run baseline then thunked (set QEMU= and PLUGIN=)
# make clean remove the generated src/ build/ thunks/
# make distclean also remove the downloaded devkit and tarball
#
# Set DEVKIT= to reuse an already-unpacked devkit (then nothing is
downloaded).
# Override VERSION= or ARCH= to pick a different release or host
architecture.
VERSION ?= 1.0.5.0
ARCH ?= $(shell uname -m)
DEVKIT ?= lorelei-devkit-$(ARCH)
TARBALL := $(DEVKIT)-$(VERSION).tar.xz
URL :=
https://github.com/rover2024/lorelei/releases/download/v$(VERSION)/$(TARBALL)
QEMU ?=
PLUGIN ?=
CLANG = $(DEVKIT)/bin/x86_64-linux-gnu-clang
MKTHUNK = $(DEVKIT)/bin/LoreMakeThunk.py
GTL = thunks/x86_64/lib/x86_64-LoreGTL
.PHONY: all tree run clean distclean
all: build/guest/main $(GTL)/libhello.so
# 0. the devkit, downloaded and unpacked only when $(MKTHUNK) is missing, so
# pointing DEVKIT= at an existing devkit skips the download.
$(MKTHUNK):
@echo ">> downloading $(TARBALL)"
@command -v wget >/dev/null 2>&1 && wget -O $(TARBALL) $(URL) \
|| curl -fSL -o $(TARBALL) $(URL)
tar -xf $(TARBALL)
# 1. the sources, written out so the whole tree comes from this one
Makefile.
# The guest and host builds print "from guest" and "from host", so a run
shows
# which one ran.
src/hello.h:
@mkdir -p src
@printf '%s\n' \
'#ifdef __cplusplus' 'extern "C" {' '#endif' \
'void hello(const char *name, int lucky);' \
'#ifdef __cplusplus' '}' '#endif' > $@
src/hello_guest.c: | src/hello.h
@printf '%s\n' \
'#include "hello.h"' '#include <stdio.h>' '' \
'void hello(const char *name, int lucky)' '{' \
' printf("hello from guest: %s, lucky %d\n", name, lucky);' \
' fflush(stdout);' '}' > $@
src/hello_host.c: | src/hello.h
@printf '%s\n' \
'#include "hello.h"' '#include <stdio.h>' '' \
'void hello(const char *name, int lucky)' '{' \
' printf("hello from host: %s, lucky %d\n", name, lucky);' \
' fflush(stdout);' '}' > $@
src/main.c: | src/hello.h
@printf '%s\n' \
'#include "hello.h"' '' \
'int main(void)' '{' \
' hello("world", 7);' ' return 0;' '}' > $@
# 2. the guest libhello.so (x86_64) and the guest program. main has no
rpath,
# so which libhello.so it loads is decided by LD_LIBRARY_PATH at run time.
build/guest/main: src/hello_guest.c src/main.c src/hello.h | $(MKTHUNK)
mkdir -p build/guest
$(CLANG) -shared -fPIC src/hello_guest.c -o build/guest/libhello.so
$(CLANG) src/main.c -Isrc -Lbuild/guest -lhello -o $@
# 3. the host libhello.so, native to this host, for the host thunk to use.
build/host/libhello.so: src/hello_host.c src/hello.h
mkdir -p build/host
cc -shared -fPIC src/hello_host.c -o $@
# 4. the thunk pack (host HTL + guest GTL) generated from the host library.
$(GTL)/libhello.so: build/host/libhello.so | $(MKTHUNK)
$(MKTHUNK) --name hello --lib $< --header hello.h -o thunks -- -Isrc
# print the produced tree
tree: all
@command -v tree >/dev/null 2>&1 && tree src build thunks \
|| find src build thunks | sort
# run baseline (guest build) then thunked (host build) under qemu.
run: all
@echo "== without the thunk =="
$(QEMU) -E LD_LIBRARY_PATH=build/guest build/guest/main
@echo "== with the thunk =="
LORELEI_THUNK_PATH=thunks LD_LIBRARY_PATH=$(DEVKIT)/lib:build/host \
$(QEMU) -plugin $(PLUGIN) \
-E LD_LIBRARY_PATH=$(DEVKIT)/x86_64/lib:$(GTL) \
build/guest/main
clean:
rm -rf src build thunks
distclean: clean
rm -rf $(DEVKIT) $(TARBALL)