Skip to content

Commit

Permalink
fixup! [WIP] Make the JIT'd code completely portable.
Browse files Browse the repository at this point in the history
Add arm64
  • Loading branch information
hawkinsw committed Apr 27, 2024
1 parent a7730c7 commit 2e13f7c
Show file tree
Hide file tree
Showing 8 changed files with 441 additions and 73 deletions.
@@ -0,0 +1 @@
8f 00 00 00 01 00 00 00
Empty file.
135 changes: 125 additions & 10 deletions custom_tests/srcs/test_helpers.h
Expand Up @@ -109,20 +109,135 @@ updated_dispatcher_test_memfrob(uint64_t a, uint64_t b, uint64_t c, uint64_t d,
return 43;
}

static uint64_t
dispatcher_gather_bytes(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e)
{
UNREFERENCED_PARAMETER(a);
UNREFERENCED_PARAMETER(b);
UNREFERENCED_PARAMETER(c);
UNREFERENCED_PARAMETER(d);
UNREFERENCED_PARAMETER(e);
return 44;

}

static uint64_t
updated_dispatcher_gather_bytes(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e)
{
UNREFERENCED_PARAMETER(a);
UNREFERENCED_PARAMETER(b);
UNREFERENCED_PARAMETER(c);
UNREFERENCED_PARAMETER(d);
UNREFERENCED_PARAMETER(e);
return 45;
}

static uint64_t
dispatcher_no_op(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e)
{
UNREFERENCED_PARAMETER(a);
UNREFERENCED_PARAMETER(b);
UNREFERENCED_PARAMETER(c);
UNREFERENCED_PARAMETER(d);
UNREFERENCED_PARAMETER(e);
return 46;

}

static uint64_t
updated_dispatcher_no_op(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e)
{
UNREFERENCED_PARAMETER(a);
UNREFERENCED_PARAMETER(b);
UNREFERENCED_PARAMETER(c);
UNREFERENCED_PARAMETER(d);
UNREFERENCED_PARAMETER(e);
return 47;
}

static uint64_t
dispatcher_sqrti(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e)
{
UNREFERENCED_PARAMETER(a);
UNREFERENCED_PARAMETER(b);
UNREFERENCED_PARAMETER(c);
UNREFERENCED_PARAMETER(d);
UNREFERENCED_PARAMETER(e);
return 48;

}

static uint64_t
updated_dispatcher_sqrti(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e)
{
UNREFERENCED_PARAMETER(a);
UNREFERENCED_PARAMETER(b);
UNREFERENCED_PARAMETER(c);
UNREFERENCED_PARAMETER(d);
UNREFERENCED_PARAMETER(e);
return 49;
}

static uint64_t
dispatcher_strcmp_ext(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e)
{
UNREFERENCED_PARAMETER(a);
UNREFERENCED_PARAMETER(b);
UNREFERENCED_PARAMETER(c);
UNREFERENCED_PARAMETER(d);
UNREFERENCED_PARAMETER(e);
return 50;

}

static uint64_t
updated_dispatcher_strcmp_ext(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e)
{
UNREFERENCED_PARAMETER(a);
UNREFERENCED_PARAMETER(b);
UNREFERENCED_PARAMETER(c);
UNREFERENCED_PARAMETER(d);
UNREFERENCED_PARAMETER(e);
return 51;
}

static uint64_t
dispatcher_unwind(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e)
{
UNREFERENCED_PARAMETER(a);
UNREFERENCED_PARAMETER(b);
UNREFERENCED_PARAMETER(c);
UNREFERENCED_PARAMETER(d);
UNREFERENCED_PARAMETER(e);
return 52;

}

static uint64_t
updated_dispatcher_unwind(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e)
{
UNREFERENCED_PARAMETER(a);
UNREFERENCED_PARAMETER(b);
UNREFERENCED_PARAMETER(c);
UNREFERENCED_PARAMETER(d);
UNREFERENCED_PARAMETER(e);
return 53;
}

static std::map<uint32_t, external_function_t> dispatch_test_helper_functions = {
{0, gather_bytes},
{0, dispatcher_gather_bytes},
{1, dispatcher_test_memfrob },
{2, no_op},
{3, sqrti},
{4, strcmp_ext},
{5, unwind},
{2, dispatcher_no_op},
{3, dispatcher_sqrti},
{4, dispatcher_strcmp_ext},
{5, dispatcher_unwind},
};

static std::map<uint32_t, external_function_t> updated_dispatch_test_helper_functions = {
{0, gather_bytes},
{0, updated_dispatcher_gather_bytes},
{1, updated_dispatcher_test_memfrob },
{2, no_op},
{3, sqrti},
{4, strcmp_ext},
{5, unwind},
{2, updated_dispatcher_no_op},
{3, updated_dispatcher_sqrti},
{4, updated_dispatcher_strcmp_ext},
{5, updated_dispatcher_unwind},
};
1 change: 1 addition & 0 deletions custom_tests/srcs/ubpf_custom_test_support.cc
Expand Up @@ -67,6 +67,7 @@ bool ubpf_setup_custom_test(ubpf_vm_up &vm,
ubpf_jit_fn &jit_fn,
std::string &error)
{
jit_fn = nullptr;
std::vector<ebpf_inst> program = bytes_to_ebpf_inst(base16_decode(program_string));
char *error_s{nullptr};

Expand Down
48 changes: 48 additions & 0 deletions custom_tests/srcs/ubpf_test_jit_unexpected_instruction.cc
@@ -0,0 +1,48 @@
// Copyright (c) Microsoft Corporation
// SPDX-License-Identifier: Apache-2.0

#include <vector>
#include <string>
#include <iostream>

extern "C"
{
#include "ebpf.h"
#include "ubpf.h"
}

#include "ubpf_custom_test_support.h"

/**
* @brief This program reads BPF instructions from stdin and memory contents from
* the first agument. It then executes the BPF program and prints the
* value of %r0 at the end of execution.
*/
int main()
{
std::string expected_error{"Failed to load program: unknown opcode 0x8f at PC 0" };
ubpf_jit_fn jit_fn;

std::string program_string;
std::getline(std::cin, program_string);

std::vector<ebpf_inst> program = bytes_to_ebpf_inst(base16_decode(program_string));

ubpf_vm_up vm(ubpf_create(), ubpf_destroy);
std::string error{};

if (!ubpf_setup_custom_test(
vm,
program_string,
custom_test_fixup_cb{[](ubpf_vm_up&, std::string& ) {
return true;
}},
jit_fn,
error)) {

if (jit_fn == nullptr && expected_error == error)
return 0;
}

return 1;
}
133 changes: 102 additions & 31 deletions custom_tests/srcs/ubpf_test_update_helpers.cc
Expand Up @@ -15,13 +15,21 @@

extern "C"
{
#include "ebpf.h"
#include "ubpf.h"
}

#include "ubpf_custom_test_support.h"
#include "test_helpers.h"

struct HelperTestCase {
const char *testcase_name;
external_function_t helper_function1;
external_function_t helper_function2;
int index;
uint64_t result1;
uint64_t result2;
};

/**
* @brief This program reads BPF instructions from stdin and memory contents from
* the first agument. It then executes the BPF program and prints the
Expand All @@ -31,42 +39,105 @@ int main(int argc, char **argv)
{
std::vector<std::string> args(argv, argv + argc);
std::string program_string{};
ubpf_jit_fn jit_fn;
uint64_t memory{0x123456789};
bool success{true};

const char memfrob_testcase_name[] = "memfrob";
const char gather_bytes_testcase_name[] = "gather bytes";
const char sqrti_testcase_name[] = "sqrti";
const char no_op_testcase_name[] = "no op";
const char strcmp_testcase_name[] = "strcmp";
const char unwind_testcase_name[] = "unwind";

std::vector<HelperTestCase> test_cases{
{
.testcase_name = memfrob_testcase_name,
.helper_function1 = dispatcher_test_memfrob,
.helper_function2 = updated_dispatcher_test_memfrob,
.index = 1,
.result1 = 42,
.result2 = 43
},
{
.testcase_name = gather_bytes_testcase_name,
.helper_function1 = dispatcher_gather_bytes,
.helper_function2 = updated_dispatcher_gather_bytes,
.index = 1,
.result1 = 44,
.result2 = 45
},
{
.testcase_name = no_op_testcase_name,
.helper_function1 = dispatcher_no_op,
.helper_function2 = updated_dispatcher_no_op,
.index = 1,
.result1 = 46,
.result2 = 47
},
{
.testcase_name = sqrti_testcase_name,
.helper_function1 = dispatcher_sqrti,
.helper_function2 = updated_dispatcher_sqrti,
.index = 1,
.result1 = 48,
.result2 = 49
},
{
.testcase_name = strcmp_testcase_name,
.helper_function1 = dispatcher_strcmp_ext,
.helper_function2 = updated_dispatcher_strcmp_ext,
.index = 1,
.result1 = 50,
.result2 = 51
},
{
.testcase_name = unwind_testcase_name,
.helper_function1 = dispatcher_unwind,
.helper_function2 = updated_dispatcher_unwind,
.index = 1,
.result1 = 52,
.result2 = 53
}
};

std::getline(std::cin, program_string);

std::unique_ptr<ubpf_vm, decltype(&ubpf_destroy)> vm(ubpf_create(), ubpf_destroy);
std::string error{};
if (!ubpf_setup_custom_test(
vm,
program_string,
[](ubpf_vm_up& vm, std::string& error) {
for (auto& [key, value] : dispatch_test_helper_functions) {
if (ubpf_register(vm.get(), key, "unnamed", value) != 0) {
error = "Failed to register helper function";
return false;
}
}
return true;
},
jit_fn,
error)) {
std::cerr << "Problem setting up custom test: " << error << std::endl;
return 1;
}
for (auto testcase : test_cases) {
ubpf_jit_fn jit_fn;
uint64_t memory{0x123456789};
std::unique_ptr<ubpf_vm, decltype(&ubpf_destroy)> vm(ubpf_create(), ubpf_destroy);
std::string error{};
if (!ubpf_setup_custom_test(
vm,
program_string,
[&testcase](ubpf_vm_up& vm, std::string& error) {
if (ubpf_register(vm.get(), testcase.index, "unnamed", testcase.helper_function1) != 0) {
error = "Failed to register helper function";
return false;
}
return true;
},
jit_fn,
error)) {
std::cerr << "Problem setting up custom test: " << error << std::endl;
return 1;
}

[[maybe_unused]] auto first_result = jit_fn(&memory, sizeof(uint64_t));
std::cout << "first_result: " << first_result << "\n";
[[maybe_unused]] auto first_result = jit_fn(&memory, sizeof(uint64_t));

for (auto& [key, value] : updated_dispatch_test_helper_functions) {
if (ubpf_register(vm.get(), key, "unnamed", value) != 0) {
error = "Failed to register helper function";
if (ubpf_register(vm.get(), testcase.index, "unnamed", testcase.helper_function2) != 0) {
std::cout << "Failed to register helper function\n";
return 1;
}
}

[[maybe_unused]] auto second_result = jit_fn(&memory, sizeof(uint64_t));
std::cout << "second_result: " << second_result << "\n";
return !(first_result == 42);
[[maybe_unused]] auto second_result = jit_fn(&memory, sizeof(uint64_t));

auto current_success{(first_result == testcase.result1 && second_result == testcase.result2)};
if (!current_success) {
std::cout << "There was a failure with test " << testcase.testcase_name << ": " <<
testcase.result1 << " != " << first_result << " or " <<
testcase.result2 << " != " << second_result << "!\n";
}
success &= current_success;
}
return success ? 0 : 1;
}

0 comments on commit 2e13f7c

Please sign in to comment.