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)


Reply via email to