Skip to content

Commit

Permalink
CI: fix vm test and add llvm ir generate (#1)
Browse files Browse the repository at this point in the history
* update llvm ir example

* fix test

* update CI

* fix input

* add

* fix
  • Loading branch information
yunwei37 authored Aug 11, 2024
1 parent a73c97e commit 41ae095
Show file tree
Hide file tree
Showing 13 changed files with 129 additions and 44 deletions.
41 changes: 32 additions & 9 deletions .github/workflows/test-vm.yml
Original file line number Diff line number Diff line change
@@ -1,30 +1,53 @@
name: Build and Test VM
name: Build and Test VM input and output

on:
push:
branches: [ master ]
branches: [ main ]
pull_request:
branches: [ master ]
branches: [ main ]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
container:
- ubuntu-2204
- fedora-39
container:
image: "manjusakalza/bpftime-base-image:${{matrix.container}}"
options: --privileged
steps:

- name: cache dependencies
uses: actions/cache@v2
id: cache
with:
path: ${{ github.workspace }}/${{ env.INSTALL_LOCATION }}
key: ${{ runner.os }}-dependencies

- uses: actions/checkout@v2
with:
submodules: 'recursive'

- uses: actions/setup-python@v4
if: startsWith(matrix.container,'ubuntu')
with:
python-version: '3.8'

- name: build
run:
|
sudo apt install llvm-15-dev
cmake -B build -DCMAKE_BUILD_TYPE=Debug
cmake -B build -DCMAKE_BUILD_TYPE=Debug -DBPFTIME_ENABLE_UNIT_TESTING=1
cmake --build build --target all -j

- name: run testsuit x86
shell: bash
run: |
python3.8 -m venv vm/test
source vm/test/bin/activate
pip install -r vm/test/requirements.txt
python3.8 -m venv ./test
source test/bin/activate
pip install -r test/requirements.txt
# make build # or build-arm32 build-arm64
make -C vm test-vm -j
pytest -v -s test/test_framework
2 changes: 1 addition & 1 deletion .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
- name: Run tests
run: |
./build/unit-test/llvm_jit_tests
./build/test/unit-test/llvm_jit_tests
- name: build llvm JIT/AOT release as a standalone library
run: |
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ compile_commands.json
libbpftime_llvm_jit_vm.a
test.o
test.bin
*.ll
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ add_dependencies(bpftime_llvm_jit_vm spdlog::spdlog)

if(BPFTIME_ENABLE_UNIT_TESTING)
message(STATUS "Build unit tests for the project. Tests should always be found in the test folder\n")
add_subdirectory(unit-test)
add_subdirectory(test)
endif()

add_subdirectory(example)
42 changes: 39 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,50 @@ void run_ebpf_prog(const void *code, size_t code_len)
## Use llvmbpf as a AOT compiler
You can use the cli to generate the LLVM IR from eBPF bytecode:
```console
# ./build/cli/bpftime-vm build .github/assets/sum.bpf.o -emit-llvm > test.bpf.ll
# opt -O3 -S test.bpf.ll -opaque-pointers -o test.opt.ll
# cat test.opt.ll
; ModuleID = 'test.bpf.ll'
source_filename = "bpf-jit"
; Function Attrs: nofree norecurse nosync nounwind memory(read, inaccessiblemem: none)
define i64 @bpf_main(ptr %0, i64 %1) local_unnamed_addr #0 {
setupBlock:
%2 = ptrtoint ptr %0 to i64
%3 = load i32, ptr %0, align 4
%4 = icmp slt i32 %3, 1
br i1 %4, label %bb_inst_30, label %bb_inst_15
bb_inst_15: ; preds = %setupBlock, %bb_inst_15
%storemerge32 = phi i32 [ %11, %bb_inst_15 ], [ 1, %setupBlock ]
%stackBegin29.sroa.2.031 = phi i32 [ %10, %bb_inst_15 ], [ 0, %setupBlock ]
%5 = sext i32 %storemerge32 to i64
%6 = shl nsw i64 %5, 2
%7 = add i64 %6, %2
%8 = inttoptr i64 %7 to ptr
%9 = load i32, ptr %8, align 4
%10 = add i32 %9, %stackBegin29.sroa.2.031
%11 = add i32 %storemerge32, 1
%12 = icmp sgt i32 %11, %3
br i1 %12, label %bb_inst_30, label %bb_inst_15
bb_inst_30: ; preds = %bb_inst_15, %setupBlock
%stackBegin29.sroa.2.0.lcssa = phi i32 [ 0, %setupBlock ], [ %10, %bb_inst_15 ]
%13 = zext i32 %stackBegin29.sroa.2.0.lcssa to i64
ret i64 %13
}
attributes #0 = { nofree norecurse nosync nounwind memory(read, inaccessiblemem: none) }
```

AOT Compile a eBPF program:

```console
# ./build/cli/bpftime-vm build .github/assets/sum.bpf.o
[2024-08-10 14:54:06.453] [info] [main.cpp:56] Processing program test
[2024-08-10 14:54:06.454] [info] [llvm_jit_context.cpp:242] Initializing llvm
[2024-08-10 14:54:06.477] [info] [llvm_jit_context.cpp:342] AOT: done, received 544 bytes
[2024-08-10 14:54:06.479] [info] [main.cpp:69] Program test written to ./test.o
```

Expand All @@ -66,7 +103,6 @@ Load and run a AOTed eBPF program:
```console
# echo "AwAAAAEAAAACAAAAAwAAAA==" | base64 -d > test.bin
# ./build/cli/bpftime-vm run test.o test.bin
[2024-08-10 14:57:16.986] [info] [llvm_jit_context.cpp:242] Initializing llvm
[2024-08-10 14:57:16.986] [info] [llvm_jit_context.cpp:392] LLVM-JIT: Loading aot object
[2024-08-10 14:57:16.991] [info] [main.cpp:136] Program executed successfully. Return value: 6
```
Expand Down
55 changes: 39 additions & 16 deletions cli/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@
#include "llvmbpf.hpp"

extern "C" {
struct bpf_object;
struct bpf_program;
struct bpf_insn;
void bpf_object__close(bpf_object *obj);
bpf_program *bpf_object__next_program(const bpf_object *obj, bpf_program *prog);
const char *bpf_program__name(const bpf_program *prog);
bpf_object *bpf_object__open(const char *path);
const bpf_insn *bpf_program__insns(const bpf_program *prog);
size_t bpf_program__insn_cnt(const bpf_program *prog);
struct bpf_object;
struct bpf_program;
struct bpf_insn;
void bpf_object__close(bpf_object *obj);
bpf_program *bpf_object__next_program(const bpf_object *obj, bpf_program *prog);
const char *bpf_program__name(const bpf_program *prog);
bpf_object *bpf_object__open(const char *path);
const bpf_insn *bpf_program__insns(const bpf_program *prog);
size_t bpf_program__insn_cnt(const bpf_program *prog);
}

using namespace bpftime;
Expand All @@ -31,8 +31,9 @@ static void print_usage(const std::string &program_name)
std::cerr
<< "Usage: " << program_name << " <command> [options]\n"
<< "Commands:\n"
<< " build <EBPF_ELF> [-o <output_directory>]\n"
<< " build <EBPF_ELF> [-o <output_directory>] [-emit-llvm]\n"
<< " Build native ELF(s) from eBPF ELF. Each program in the eBPF ELF will be built into a single native ELF.\n"
<< " If -emit-llvm is specified, the LLVM IR will be printed to stdout.\n"
<< " run <PATH> [MEMORY]\n"
<< " Run a native eBPF program.\n";
}
Expand All @@ -47,8 +48,19 @@ parse_optional_argument(int argc, const char **argv, int &i,
return std::nullopt;
}

static bool has_argument(int argc, const char **argv, const std::string &option)
{
for (int i = 0; i < argc; ++i) {
if (std::string(argv[i]) == option) {
return true;
}
}
return false;
}

static int build_ebpf_program(const std::string &ebpf_elf,
const std::filesystem::path &output)
const std::filesystem::path &output,
bool emit_llvm)
{
bpf_object *obj = bpf_object__open(ebpf_elf.c_str());
if (!obj) {
Expand All @@ -61,8 +73,9 @@ static int build_ebpf_program(const std::string &ebpf_elf,
for ((prog) = bpf_object__next_program((elf.get()), __null);
(prog) != __null;
(prog) = bpf_object__next_program((elf.get()), (prog))) {
const char* name = bpf_program__name(prog);
SPDLOG_INFO("Processing program {}", name);
const char *name = bpf_program__name(prog);
if (!emit_llvm)
SPDLOG_INFO("Processing program {}", name);
bpftime_llvm_jit_vm vm;

if (vm.load_code((const void *)bpf_program__insns(prog),
Expand All @@ -73,11 +86,19 @@ static int build_ebpf_program(const std::string &ebpf_elf,
name, vm.get_error_message());
return 1;
}
auto result = vm.do_aot_compile(false);
// add 1000 pesudo helpers so it can be used with helpers
for (int i = 0; i < 1000; i++) {
vm.register_external_function(
i, "helper_" + std::to_string(i), nullptr);
}
auto result = vm.do_aot_compile(emit_llvm);

auto out_path = output / (std::string(name) + ".o");
std::ofstream ofs(out_path, std::ios::binary);
ofs.write((const char *)result.data(), result.size());
SPDLOG_INFO("Program {} written to {}", name, out_path.c_str());
if (!emit_llvm)
SPDLOG_INFO("Program {} written to {}", name,
out_path.c_str());
}
return 0;
}
Expand Down Expand Up @@ -185,7 +206,9 @@ int main(int argc, const char **argv)
}
}

return build_ebpf_program(ebpf_elf, output);
bool emit_llvm = has_argument(argc, argv, "-emit-llvm");

return build_ebpf_program(ebpf_elf, output, emit_llvm);
} else if (command == "run") {
if (argc < 3) {
print_usage(argv[0]);
Expand Down
10 changes: 5 additions & 5 deletions src/llvm_jit_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,13 +233,13 @@ extern "C" void __aeabi_unwind_cpp_pr1();

static int llvm_initialized = 0;

llvm_bpf_jit_context::llvm_bpf_jit_context(bpftime_llvm_jit_vm& vm) : vm(vm)
llvm_bpf_jit_context::llvm_bpf_jit_context(bpftime_llvm_jit_vm &vm) : vm(vm)
{
using namespace llvm;
int zero = 0;
if (__atomic_compare_exchange_n(&llvm_initialized, &zero, 1, false,
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
SPDLOG_INFO("Initializing llvm");
SPDLOG_DEBUG("Initializing llvm");
InitializeNativeTarget();
InitializeNativeTargetAsmPrinter();
}
Expand Down Expand Up @@ -286,7 +286,7 @@ std::vector<uint8_t> llvm_bpf_jit_context::do_aot_compile(
return module->withModuleDo([&](auto &module)
-> std::vector<uint8_t> {
if (print_ir) {
module.print(errs(), nullptr);
module.print(llvm::outs(), nullptr);
}
optimizeModule(module);
module.setTargetTriple(defaultTargetTriple);
Expand Down Expand Up @@ -339,8 +339,8 @@ std::vector<uint8_t> llvm_bpf_jit_context::do_aot_compile(
}

pass.run(module);
SPDLOG_INFO("AOT: done, received {} bytes",
objStream.size());
SPDLOG_DEBUG("AOT: done, received {} bytes",
objStream.size());

std::vector<uint8_t> result(objStream.begin(),
objStream.end());
Expand Down
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ project(
)

add_subdirectory(bpf_conformance_runner)
add_subdirectory(unit-test)

message(DEBUG "Adding tests under ${CMAKE_PROJECT_NAME}Tests...")

Expand Down
4 changes: 2 additions & 2 deletions test/bpf_conformance_runner/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ add_executable(bpftime_vm_bpf_conformance_runner
main-bpf-conformance.cpp
)

add_dependencies(bpftime_vm_bpf_conformance_runner bpftime_vm)
target_link_libraries(bpftime_vm_bpf_conformance_runner bpftime_vm)
add_dependencies(bpftime_vm_bpf_conformance_runner bpftime_llvm_jit_vm)
target_link_libraries(bpftime_vm_bpf_conformance_runner bpftime_llvm_jit_vm)

set_target_properties(bpftime_vm_bpf_conformance_runner PROPERTIES CXX_STANDARD 20)
15 changes: 8 additions & 7 deletions test/bpf_conformance_runner/main-bpf-conformance.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "bpftime_vm_compat.hpp"
#include "llvmbpf.hpp"
#include "ebpf_inst.h"
#include <cassert>
#include <cstdint>
Expand All @@ -7,6 +7,8 @@
#include <sstream>
#include <vector>

using namespace bpftime;

/**
* @brief Read in a string of hex bytes and return a vector of bytes.
*
Expand Down Expand Up @@ -102,17 +104,16 @@ int main(int argc, char **argv)
std::string log;

int err;
auto vm = create_vm_instance();
assert(vm);
err = vm->load_code(&program[0], program.size() * 8);
auto vm = bpftime_llvm_jit_vm();
err = vm.load_code(&program[0], program.size() * sizeof(ebpf_inst));
if (err < 0) {
std::cerr << "Error: " << vm->get_error_message() << std::endl;
std::cerr << "Error: " << vm.get_error_message() << std::endl;
return -1;
}
auto func = vm->compile();
auto func = vm.compile();
assert(func);
uint64_t res;
vm->exec(&memory[0], memory.size(), res);
vm.exec(&memory[0], memory.size(), res);
std::cout << std::hex << res << std::endl;
return 0;
}
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 comments on commit 41ae095

Please sign in to comment.