We designed and implemented bof-launcher with a portability in mind so running BOFs on Linux ARM-based devices is a snap. Below, we’re running our uname BOF on Raspberry Pi device. For convenience we use our cli4bofs tool to execute BOF directly from command line. So let’s jump to our device:

With Zig and our carefully crafted build.zig files (i.e. Makefiles on steroids) cross-compilation is happening out-of-the-box no matter on which platform (Linux / Windows) you’re building, so usual build zig will build BOFs from bofs/ drectory for every supported platform:

[bof-launcher]$ zig build >/dev/null; ls -al zig-out/bin/uname.elf.*
-rw-r--r-- 1 mz mz 5032 05-10 11:11 zig-out/bin/uname.elf.aarch64.o
-rw-r--r-- 1 mz mz 4012 05-10 11:11 zig-out/bin/uname.elf.arm.o
-rw-r--r-- 1 mz mz 4952 05-10 11:11 zig-out/bin/uname.elf.x64.o
-rw-r--r-- 1 mz mz 3592 05-10 11:11 zig-out/bin/uname.elf.x86.o

Finally we will fetch latest binaries of cli4bofs tool (see the releases at: https://github.com/The-Z-Labs/cli4bofs/tags) onto the device and (after uploading uname BOF onto the device) run our BOF:

As a second example we will run BOF from TRUSTEDSEC’s ELFLoader project. We will build their cat BOF using bof-launcher to demonstrate how easy and convenient it is to build 3rd party BOFs with it. In bof-launcher/bofs/ directory we will find build.zig file that defines which BOFs should be built and for which architectures, as shown below:

const bofs_included_in_launcher = [_]Bof{
    .{ .name = "helloBof", .formats = &.{.elf}, .archs = &.{ .x64, .x86, .aarch64, .arm } },
    .{ .name = "udpScanner", .formats = &.{ .elf, .coff }, .archs = &.{ .x64, .x86, .aarch64, .arm } },.{ .name = "udpScanner", .formats = &.{ .elf, .coff }, .archs = &.{ .x64, .x86, .aarch64, .arm } },
    .{ .name = "ifconfig", .dir = "net-tools/", .formats = &.{.elf}, .archs = &.{ .x64, .x86, .aarch64, .arm } },
    // ...

There’s also second array specifically for adding 3rd party BOFs, let’s uncomment it and add cat BOF there for desired architectures, for clarity we will also expect it in a seperate directory trustedsec:

const bofs_my_custom = [_]Bof{
    .{ .name = "cat", .dir = "trustedsec/", .formats = &.{ .elf }, .archs = &.{ .x64, .x86, .aarch64, .arm } },

fn addBofsToBuild(bofs_to_build: *std.ArrayList(Bof)) !void {
    try bofs_to_build.appendSlice(bofs_included_in_launcher[0..]);

    try bofs_to_build.appendSlice(bofs_my_custom[0..]);

Now, let’s fetch the sources:

cd bof-launcher/bofs/src
mkdir trustedsec
wget https://raw.githubusercontent.com/trustedsec/ELFLoader/main/SA/src/cat.c -O trustedsec/cat.c

One last step before building it is to change name of beacon header file (ELFloader project uses beacon_api.h instead of beacon.h):

sed -i s/beacon_api.h/beacon.h/g trustedsec/cat.c

Let’s return to bof-launcher main directory and build it:

cd ../../
zig build >/dev/null
$ ls zig-out/bin/cat.elf.*
zig-out/bin/cat.elf.aarch64.o  zig-out/bin/cat.elf.arm.o  zig-out/bin/cat.elf.x64.o  zig-out/bin/cat.elf.x86.o

After copying it onto the Pi device, we can run it: