Remove Linux + parcon dependency (#906)

* Remove Linux + parcon dependency

Signed-off-by: Alan Jowett <alanjo@microsoft.com>

* Remove Linux + parcon dependency

Signed-off-by: Alan Jowett <alanjo@microsoft.com>

* Set path to compiler

Signed-off-by: Alan Jowett <alanjo@microsoft.com>

* Fix the build

Signed-off-by: Alan Jowett <alanjo@microsoft.com>

* Fix build

Signed-off-by: Alan Jowett <alanjo@microsoft.com>

* PR feedbac

Signed-off-by: Alan Jowett <alanjo@microsoft.com>

* PR feedback

Signed-off-by: Alan Jowett <alanjo@microsoft.com>
This commit is contained in:
Alan Jowett 2022-04-07 18:19:04 -06:00 коммит произвёл GitHub
Родитель 59716dfa16
Коммит b06f6ac820
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
12 изменённых файлов: 471 добавлений и 112 удалений

55
.github/workflows/bpf2c-test.yml поставляемый
Просмотреть файл

@ -13,49 +13,54 @@ permissions:
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
configurations: [Debug, Release]
runs-on: windows-2019
env:
# Path to the solution file relative to the root of the project.
SOLUTION_FILE_PATH: ebpf-for-windows.sln
# Configuration type to build.
# You can convert this to a build matrix if you need coverage of multiple configuration types.
# https://docs.github.com/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
BUILD_CONFIGURATION: ${{matrix.configurations}}
BUILD_PLATFORM: x64
steps:
- name: Harden Runner
uses: step-security/harden-runner@9b0655f430fba8c7001d4e38f8d4306db5c6e0ab
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- uses: actions/checkout@b0e28b5ac45a892f91e7d036f8200cf5ed489415
with:
submodules: 'recursive'
- name: Install Dependencies
working-directory: ${{env.GITHUB_WORKSPACE}}
run: |
sudo apt-get update
sudo apt-get -y install python3 python3-pip python3-setuptools python3-wheel nuget
python3 -m pip install external/parcon
python3 -m pip install --require-hash -r tests/bpf2c_tests/requirements.txt
- name: Add MSBuild to PATH
uses: microsoft/setup-msbuild@becb80cf9a036187bb1e07e74eb64e25850d757a
- name: Restore nuget packages
- name: Install Tools
working-directory: ${{env.GITHUB_WORKSPACE}}
run: |
nuget restore
choco install -y --requirechecksum=true --checksum=2295A733DA39412C61E4F478677519DD0BB1893D88313CE56B468C9E50517888 --checksum-type=sha256 OpenCppCoverage
echo "C:\Program Files\OpenCppCoverage" >> $env:GITHUB_PATH
- name: Fix include folder
- name: Create catch2 project
working-directory: ${{env.GITHUB_WORKSPACE}}
run: |
rm -rf include/asm include/linux
cmake -G "Visual Studio 16 2019" -S external\catch2 -B external\catch2\build -DBUILD_TESTING=OFF
- name: Build & run tests
- name: Build
working-directory: ${{env.GITHUB_WORKSPACE}}
run: msbuild /m /p:Configuration=${{env.BUILD_CONFIGURATION}} /p:Platform=${{env.BUILD_PLATFORM}} ${{env.SOLUTION_FILE_PATH}} /target:tests\bpf2c_tests
# Run bpf2c_tests.exe.exe and generate ebpf_for_windows.xml
- name: Generate Report - bpf2c Tests
shell: cmd
run: |
export CXXFLAGS="--coverage -g -O0"
cd tests/bpf2c_tests
make
./bpf2c_tests -s
gcovr -r ../.. --cobertura ../../bpf2c.xml --gcov-ignore-parse-errors
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\VsDevCmd.bat"
OpenCppCoverage.exe --sources %CD% --excluded_sources %CD%\external\Catch2 --export_type cobertura:ebpf_for_windows_%BUILD_CONFIGURATION%.xml --working_dir %BUILD_PLATFORM%\%BUILD_CONFIGURATION% -- %BUILD_PLATFORM%\%BUILD_CONFIGURATION%\bpf2c_tests.exe -s
- name: Upload Report to Codecov
uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b
with:
files: bpf2c.xml
files: ebpf_for_windows_${{env.BUILD_CONFIGURATION}}.xml
fail_ci_if_error: true
functionalities: fix

3
.gitmodules поставляемый
Просмотреть файл

@ -16,6 +16,3 @@
[submodule "external/Catch2"]
path = external/Catch2
url = https://github.com/catchorg/Catch2.git
[submodule "external/parcon"]
path = external/parcon
url = https://github.com/javawizard/parcon.git

1
external/parcon поставляемый

@ -1 +0,0 @@
Subproject commit 1e4e5422c1339658fd0977998ae811662307bc46

Просмотреть файл

@ -1,13 +0,0 @@
# Copyright (c) Microsoft Corporation
# SPDX-License-Identifier: MIT
FLAGS = $(CXXFLAGS) -Wall -g -std=c++17 -fPIE -Wno-unknown-pragmas
CC = g++
INCLUDES = -I../../include -I../../packages/CatchOrg.Catch.2.8.0/lib/native/include -I../../external/ubpf/vm -I../../external/ebpf-verifier/external/ELFIO -I../../tools/bpf2c/ -I../../tests/libs/util
bpf2c_tests: ../../tools/bpf2c/bpf_code_generator.cpp raw_bpf.cpp ../../tools/bpf2c/btf_parser.cpp
${CC} ${FLAGS} ${INCLUDES} $^ -o $@
clean:
rm -f *.o bpf2c_tests *.data.* *.data

Просмотреть файл

@ -4,7 +4,6 @@
SPDX-License-Identifier: MIT
-->
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\packages\CatchOrg.Catch.2.8.0\build\native\CatchOrg.Catch.props" Condition="Exists('..\..\packages\CatchOrg.Catch.2.8.0\build\native\CatchOrg.Catch.props')" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@ -141,16 +140,14 @@
<FileType>CppCode</FileType>
</CopyFileToFolders>
<ClCompile Include="..\..\tools\bpf2c\btf_parser.cpp" />
<ClCompile Include="bpf_assembler.cpp" />
<ClCompile Include="raw_bpf.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="Makefile" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\tools\bpf2c\bpf_code_generator.h" />
<ClInclude Include="..\..\tools\bpf2c\btf.h" />
<ClInclude Include="..\..\tools\bpf2c\btf_parser.h" />
<ClInclude Include="bpf_assembler.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\external\Catch2\build\src\Catch2WithMain.vcxproj">
@ -159,10 +156,4 @@
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\packages\CatchOrg.Catch.2.8.0\build\native\CatchOrg.Catch.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\CatchOrg.Catch.2.8.0\build\native\CatchOrg.Catch.props'))" />
</Target>
</Project>

Просмотреть файл

@ -28,10 +28,9 @@
<ClCompile Include="..\..\tools\bpf2c\btf_parser.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="Makefile" />
<ClCompile Include="bpf_assembler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\tools\bpf2c\bpf_code_generator.h">
@ -43,6 +42,9 @@
<ClInclude Include="..\..\tools\bpf2c\btf_parser.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="bpf_assembler.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CopyFileToFolders Include="bpf_test.cpp">

Просмотреть файл

@ -0,0 +1,382 @@
// Copyright (c) Microsoft Corporation
// SPDX-License-Identifier: MIT
#include <array>
#include <functional>
#include <unordered_map>
#include <variant>
#include <sstream>
#include "bpf_assembler.h"
typedef std::variant<ebpf_inst, std::array<ebpf_inst, 2>> bpf_encode_result_t;
typedef std::function<bpf_encode_result_t(const std::string& mnemonic, const std::vector<std::string>& operands)>
bpf_encode_t;
static const std::unordered_map<std::string, int> _bpf_encode_register_map{
{"r0", 0},
{"r1", 1},
{"r2", 2},
{"r3", 3},
{"r4", 4},
{"r5", 5},
{"r6", 6},
{"r7", 7},
{"r8", 8},
{"r9", 9},
{"r10", 10},
};
static const std::unordered_map<std::string, int> _bpf_encode_alu_ops{
{"add", 0x0},
{"sub", 0x1},
{"mul", 0x2},
{"div", 0x3},
{"or", 0x4},
{"and", 0x5},
{"lsh", 0x6},
{"rsh", 0x7},
{"neg", 0x8},
{"mod", 0x9},
{"xor", 0xa},
{"mov", 0xb},
{"arsh", 0xc},
{"le", 0xd},
{"be", 0xd},
};
static const std::unordered_map<std::string, int> _bpf_encode_jmp_ops{
{"jeq", 0x1},
{"jgt", 0x2},
{"jge", 0x3},
{"jset", 0x4},
{"jne", 0x5},
{"jsgt", 0x6},
{"jsge", 0x7},
{"jlt", 0xa},
{"jle", 0xb},
{"jslt", 0xc},
{"jsle", 0xd},
};
static uint64_t
_decode_imm64(const std::string& str)
{
if (str.find("0x") == std::string::npos) {
return std::stoull(str);
} else {
return std::stoull(str, nullptr, 16);
}
}
static uint32_t
_decode_imm32(const std::string& str)
{
if (str.find("0x") == std::string::npos) {
return std::stoul(str);
} else {
return std::stoul(str, nullptr, 16);
}
}
static uint16_t
_decode_offset(const std::string& str)
{
if (str.find("0x") == std::string::npos) {
return static_cast<uint16_t>(std::stoul(str));
} else {
return static_cast<uint16_t>(std::stoul(str, nullptr, 16));
}
}
static uint8_t
_decode_register(const std::string& register_name)
{
auto reg = _bpf_encode_register_map.find(register_name);
if (reg == _bpf_encode_register_map.end()) {
throw std::runtime_error(std::string("Invalid register: ") + register_name);
}
return static_cast<uint8_t>(reg->second);
}
static std::tuple<uint8_t, uint16_t>
_decode_register_and_offset(const std::string& operand)
{
auto reg_start = operand.find('[');
auto reg_end = operand.find('+');
reg_end = (reg_end != std::string::npos) ? reg_end : operand.find('-');
reg_end = (reg_end != std::string::npos) ? reg_end : operand.find(']');
if (reg_start == std::string::npos || reg_end == std::string::npos) {
throw std::runtime_error(std::string("Invalid operand: ") + operand);
}
if (operand.substr(reg_end).starts_with(']')) {
return std::make_tuple<uint8_t, uint16_t>(
_decode_register(operand.substr(reg_start + 1, reg_end - reg_start - 1)), 0);
} else {
return std::make_tuple<uint8_t, uint16_t>(
_decode_register(operand.substr(reg_start + 1, reg_end - reg_start - 1)),
_decode_offset(operand.substr(reg_end)));
}
}
static bpf_encode_result_t
_encode_ld(const std::string& mnemonic, const std::vector<std::string>& operands)
{
std::array<ebpf_inst, 2> inst{};
if (mnemonic != "lddw") {
throw std::runtime_error(std::string("Invalid mnemonic: ") + mnemonic);
}
if (operands.size() != 2) {
throw std::runtime_error(std::string("Wrong operand count: ") + mnemonic);
}
inst[0].opcode = EBPF_OP_LDDW;
inst[0].dst = _decode_register(operands[0]);
uint64_t immediate = _decode_imm64(operands[1]);
inst[0].imm = static_cast<uint32_t>(immediate);
inst[1].imm = static_cast<uint32_t>(immediate >> 32);
return inst;
}
static bpf_encode_result_t
_encode_ldx(const std::string& mnemonic, const std::vector<std::string>& operands)
{
ebpf_inst inst{};
if (operands.size() != 2) {
throw std::runtime_error(std::string("Wrong operand count: ") + mnemonic);
}
inst.dst = _decode_register(operands[0]);
auto [src, offset] = _decode_register_and_offset(operands[1]);
inst.src = src;
inst.offset = offset;
if (mnemonic == "ldxb") {
inst.opcode = EBPF_OP_LDXB;
} else if (mnemonic == "ldxdw") {
inst.opcode = EBPF_OP_LDXDW;
} else if (mnemonic == "ldxh") {
inst.opcode = EBPF_OP_LDXH;
} else if (mnemonic == "ldxw") {
inst.opcode = EBPF_OP_LDXW;
} else {
throw std::runtime_error(std::string("Invalid mnemonic: ") + mnemonic);
}
return inst;
}
static bpf_encode_result_t
_encode_st(const std::string& mnemonic, const std::vector<std::string>& operands)
{
ebpf_inst inst{};
if (operands.size() != 2) {
throw std::runtime_error(std::string("Wrong operand count: ") + mnemonic);
}
auto [dst, offset] = _decode_register_and_offset(operands[0]);
inst.dst = dst;
inst.offset = offset;
if (mnemonic == "stb") {
inst.opcode = EBPF_OP_STB;
} else if (mnemonic == "stdw") {
inst.opcode = EBPF_OP_STDW;
} else if (mnemonic == "sth") {
inst.opcode = EBPF_OP_STH;
} else if (mnemonic == "stw") {
inst.opcode = EBPF_OP_STW;
} else {
throw std::runtime_error(std::string("Invalid mnemonic: ") + mnemonic);
}
inst.imm = _decode_imm32(operands[1]);
return inst;
}
static bpf_encode_result_t
_encode_stx(const std::string& mnemonic, const std::vector<std::string>& operands)
{
ebpf_inst inst{};
if (operands.size() != 2) {
throw std::runtime_error(std::string("Wrong operand count: ") + mnemonic);
}
auto [dst, offset] = _decode_register_and_offset(operands[0]);
inst.dst = dst;
inst.offset = offset;
inst.src = _decode_register(operands[1]);
if (mnemonic == "stxb") {
inst.opcode = EBPF_OP_STXB;
} else if (mnemonic == "stxdw") {
inst.opcode = EBPF_OP_STXDW;
} else if (mnemonic == "stxh") {
inst.opcode = EBPF_OP_STXH;
} else if (mnemonic == "stxw") {
inst.opcode = EBPF_OP_STXW;
} else {
throw std::runtime_error(std::string("Invalid mnemonic: ") + mnemonic);
}
return inst;
}
static bpf_encode_result_t
_encode_alu(const std::string& mnemonic, const std::vector<std::string>& operands)
{
ebpf_inst inst{};
std::string alu_op;
if (mnemonic.starts_with("be")) {
if (operands.size() != 1) {
throw std::runtime_error(std::string("Wrong operand count: ") + mnemonic);
}
inst.opcode = EBPF_OP_BE;
inst.dst = _decode_register(operands[0]);
inst.imm = _decode_imm32(mnemonic.substr(2));
return inst;
} else if (mnemonic.starts_with("le")) {
if (operands.size() != 1) {
throw std::runtime_error(std::string("Wrong operand count: ") + mnemonic);
}
inst.opcode = EBPF_OP_LE;
inst.dst = _decode_register(operands[0]);
inst.imm = _decode_imm32(mnemonic.substr(2));
return inst;
}
if (mnemonic.starts_with("neg")) {
if (operands.size() != 1) {
throw std::runtime_error(std::string("Wrong operand count: ") + mnemonic);
}
} else {
if (operands.size() != 2) {
throw std::runtime_error(std::string("Wrong operand count: ") + mnemonic);
}
}
if (mnemonic.ends_with("32")) {
inst.opcode |= EBPF_CLS_ALU;
alu_op = mnemonic.substr(0, mnemonic.size() - 2);
} else {
inst.opcode |= EBPF_CLS_ALU64;
alu_op = mnemonic;
}
auto iter = _bpf_encode_alu_ops.find(alu_op);
if (iter == _bpf_encode_alu_ops.end()) {
throw std::runtime_error(std::string("Invalid mnemonic: ") + mnemonic);
}
inst.opcode |= iter->second << 4;
inst.dst = _decode_register(operands[0]);
if (operands.size() == 2) {
if (operands[1].starts_with('r')) {
inst.opcode |= EBPF_SRC_REG;
inst.src = _decode_register(operands[1]);
} else {
inst.opcode |= EBPF_SRC_IMM;
inst.imm = _decode_imm32(operands[1]);
}
}
return inst;
}
static bpf_encode_result_t
_encode_jmp(const std::string& mnemonic, const std::vector<std::string>& operands)
{
ebpf_inst inst{};
inst.opcode |= EBPF_CLS_JMP;
if (mnemonic == "ja") {
if (operands.size() != 1) {
throw std::runtime_error(std::string("Wrong operand count: ") + mnemonic);
}
inst.offset = _decode_offset(operands[0]);
} else if (mnemonic == "exit") {
if (operands.size() != 0) {
throw std::runtime_error(std::string("Wrong operand count: ") + mnemonic);
}
inst.opcode = EBPF_OP_EXIT;
} else if (mnemonic == "call") {
if (operands.size() != 1) {
throw std::runtime_error(std::string("Wrong operand count: ") + mnemonic);
}
inst.opcode = EBPF_OP_CALL;
inst.imm = _decode_imm32(operands[0]);
} else {
if (operands.size() != 3) {
throw std::runtime_error(std::string("Wrong operand count: ") + mnemonic);
}
auto iter = _bpf_encode_jmp_ops.find(mnemonic);
inst.opcode |= iter->second << 4;
inst.dst = _decode_register(operands[0]);
if (operands[1].starts_with('r')) {
inst.opcode |= EBPF_SRC_REG;
inst.src = _decode_register(operands[1]);
} else {
inst.opcode |= EBPF_SRC_IMM;
inst.imm = _decode_imm32(operands[1]);
}
inst.offset = _decode_offset(operands[2]);
}
return inst;
}
static const std::unordered_map<std::string, bpf_encode_t> _bpf_mnemonic_map{
{"add", _encode_alu}, {"add32", _encode_alu}, {"and", _encode_alu}, {"and32", _encode_alu},
{"arsh", _encode_alu}, {"arsh32", _encode_alu}, {"be16", _encode_alu}, {"be32", _encode_alu},
{"be64", _encode_alu}, {"call", _encode_jmp}, {"div", _encode_alu}, {"div32", _encode_alu},
{"exit", _encode_jmp}, {"ja", _encode_jmp}, {"jeq", _encode_jmp}, {"jge", _encode_jmp},
{"jgt", _encode_jmp}, {"jle", _encode_jmp}, {"jlt", _encode_jmp}, {"jne", _encode_jmp},
{"jset", _encode_jmp}, {"jsge", _encode_jmp}, {"jsgt", _encode_jmp}, {"jsle", _encode_jmp},
{"jslt", _encode_jmp}, {"lddw", _encode_ld}, {"ldxb", _encode_ldx}, {"ldxdw", _encode_ldx},
{"ldxh", _encode_ldx}, {"ldxw", _encode_ldx}, {"le16", _encode_alu}, {"le32", _encode_alu},
{"le64", _encode_alu}, {"lsh", _encode_alu}, {"lsh32", _encode_alu}, {"mod", _encode_alu},
{"mod32", _encode_alu}, {"mov", _encode_alu}, {"mov32", _encode_alu}, {"mul", _encode_alu},
{"mul32", _encode_alu}, {"neg", _encode_alu}, {"neg32", _encode_alu}, {"or", _encode_alu},
{"or32", _encode_alu}, {"rsh", _encode_alu}, {"rsh32", _encode_alu}, {"stb", _encode_st},
{"stdw", _encode_st}, {"sth", _encode_st}, {"stw", _encode_st}, {"stxb", _encode_stx},
{"stxdw", _encode_stx}, {"stxh", _encode_stx}, {"stxw", _encode_stx}, {"sub", _encode_alu},
{"sub32", _encode_alu}, {"xor", _encode_alu}, {"xor32", _encode_alu},
};
std::vector<ebpf_inst>
bpf_assembler(std::istream& input)
{
std::vector<ebpf_inst> output;
std::string line;
// Parse the input stream one line at a time.
while (std::getline(input, line)) {
std::istringstream line_stream(line);
std::string mnemonic;
std::string operand;
std::vector<std::string> operands;
// Check for empty lines.
if (!std::getline(line_stream, mnemonic, ' ')) {
continue;
}
// Split the line on ' '
while (std::getline(line_stream, operand, ' ')) {
if (operand.starts_with('#')) {
break;
}
if (operand.ends_with(',')) {
operand = operand.substr(0, operand.length() - 1);
}
operands.emplace_back(operand);
}
// Find the handler for this mnemonic.
auto iter = _bpf_mnemonic_map.find(mnemonic);
if (iter == _bpf_mnemonic_map.end()) {
throw std::runtime_error(std::string("Invalid mnemonic: ") + mnemonic);
}
// Invoke handler and store result.
auto result = iter->second(mnemonic, operands);
if (std::holds_alternative<ebpf_inst>(result)) {
output.emplace_back(std::get<ebpf_inst>(result));
} else {
for (const auto& inst : std::get<std::array<ebpf_inst, 2>>(result)) {
output.emplace_back(inst);
}
}
}
return output;
}

Просмотреть файл

@ -0,0 +1,17 @@
// Copyright (c) Microsoft Corporation
// SPDX-License-Identifier: MIT
#pragma once
#include <string>
#include <vector>
#include <iostream>
#include "ebpf.h"
/**
* @brief Accept an input stream containing BPF instructions and return a vector of ebpf_inst.
*
* @param[in] input Input stream containing BPF instructions to assemble.
* @return Vector of ebpf_inst
*/
std::vector<ebpf_inst>
bpf_assembler(std::istream& input);

Просмотреть файл

@ -37,18 +37,8 @@ memfrob(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e)
};
static uint64_t
trash_registers(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e)
no_op(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e)
{
/* Overwrite all caller-save registers */
asm("mov $0xf0, %rax;"
"mov $0xf1, %rcx;"
"mov $0xf2, %rdx;"
"mov $0xf3, %rsi;"
"mov $0xf4, %rdi;"
"mov $0xf5, %r8;"
"mov $0xf6, %r9;"
"mov $0xf7, %r10;"
"mov $0xf8, %r11;");
return 0;
}
@ -73,7 +63,7 @@ unwind(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e)
std::map<uint32_t, uint64_t (*)(uint64_t r1, uint64_t r2, uint64_t r3, uint64_t r4, uint64_t r5)> helper_functions = {
{0, gather_bytes},
{1, memfrob},
{2, trash_registers},
{2, no_op},
{3, sqrti},
{4, strcmp_ext},
{5, unwind},

Просмотреть файл

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="CatchOrg.Catch" version="2.8.0" targetFramework="native" />
</packages>

Просмотреть файл

@ -4,18 +4,33 @@
#define CATCH_CONFIG_MAIN
#include "bpf_code_generator.h"
#define NUGET_CATCH
#include "catch_wrapper.hpp"
#include "bpf_assembler.h"
#define SEPERATOR "/"
#define CC "g++"
#define CXXFLAG "-g -O2"
#define EXT ".out"
#define PYTHON "python3"
#define SEPARATOR "\\"
std::string
env_or_default(const char* environment_variable, const char* default_value)
{
std::string return_value = default_value;
char* buffer = nullptr;
size_t buffer_size = 0;
if (_dupenv_s(&buffer, &buffer_size, environment_variable) == 0) {
if (buffer != nullptr) {
return_value = buffer;
}
free(buffer);
}
return return_value;
}
void
run_test(const std::string& data_file)
{
std::string cc = env_or_default("CC", "cl.exe");
std::string cxxflags = env_or_default("CXXFLAGS", "/EHsc /nologo");
enum class _state
{
state_ignore,
@ -24,11 +39,9 @@ run_test(const std::string& data_file)
state_result,
state_memory,
} state = _state::state_ignore;
std::string prefix = data_file.substr(data_file.find_last_of(SEPERATOR) + 1);
std::string prefix = data_file.substr(data_file.find_last_of(SEPARATOR) + 1);
std::string temp_asm_name = std::string(prefix) + ".asm";
std::ofstream data_out(temp_asm_name);
std::stringstream data_out;
std::ifstream data_in(data_file);
std::string result;
@ -84,31 +97,17 @@ run_test(const std::string& data_file)
continue;
}
}
data_out.flush();
data_out.close();
if (result.find("0x") != std::string::npos) {
result = result.substr(result.find("0x") + 2);
}
std::string assembler_command = std::string(PYTHON " .." SEPERATOR ".." SEPERATOR "external" SEPERATOR
"ubpf" SEPERATOR "bin" SEPERATOR "ubpf-assembler <") +
std::string(temp_asm_name) + std::string(" >") + std::string(prefix) +
std::string(".bc");
REQUIRE(system(assembler_command.c_str()) == 0);
std::ifstream bytcode_in(std::string(prefix) + std::string(".bc"), std::ios_base::in | std::ios_base::binary);
std::vector<ebpf_inst> program;
ebpf_inst instruction;
while (bytcode_in.read(reinterpret_cast<char*>(&instruction), sizeof(instruction))) {
program.push_back(instruction);
}
bytcode_in.close();
data_out.seekg(0);
auto intstructions = bpf_assembler(data_out);
std::ofstream c_file(std::string(prefix) + std::string(".c"));
try {
bpf_code_generator code("test", program);
bpf_code_generator code("test", intstructions);
code.generate("test");
code.emit_c_code(c_file);
} catch (std::runtime_error& err) {
@ -117,12 +116,12 @@ run_test(const std::string& data_file)
c_file.flush();
c_file.close();
std::string compile_command = std::string(CC " " CXXFLAG " -I.." SEPERATOR ".." SEPERATOR "include ") +
std::string(prefix) + std::string(".c ") + std::string(" bpf_test.cpp >") +
std::string(prefix) + std::string(".log -o ") + std::string(prefix) +
std::string(EXT);
std::string compile_command = cc + std::string(" ") + cxxflags +
std::string(" -I.." SEPARATOR ".." SEPARATOR "include ") + std::string(prefix) +
std::string(".c ") + std::string(" bpf_test.cpp >") + std::string(prefix) +
std::string(".log");
REQUIRE(system(compile_command.c_str()) == 0);
std::string test_command = std::string("." SEPERATOR) + std::string(prefix) + std::string(EXT) + std::string(" ") +
std::string test_command = std::string("." SEPARATOR) + std::string(prefix) + std::string(" ") +
std::string(result) + std::string(" \"") + std::string(mem) + std::string("\"");
REQUIRE(system(test_command.c_str()) == 0);
}
@ -130,7 +129,7 @@ run_test(const std::string& data_file)
#define DECLARE_TEST(FILE) \
TEST_CASE(FILE, "[raw_bpf_code_gen]") \
{ \
run_test(".." SEPERATOR ".." SEPERATOR "external" SEPERATOR "ubpf" SEPERATOR "tests" SEPERATOR "" FILE \
run_test(".." SEPARATOR ".." SEPARATOR "external" SEPARATOR "ubpf" SEPARATOR "tests" SEPARATOR "" FILE \
".data"); \
}

Просмотреть файл

@ -1,6 +0,0 @@
# Copyright (c) Microsoft Corporation
# SPDX-License-Identifier: MIT
nose == 1.3.1 --hash=sha256:85273b87ab3db9307e3b1452b071e25c1db1cc812bc337d2a97ea0b0cf2ab6ba
pyelftools == 0.27 --hash=sha256:5609aa6da1123fccfae2e8431a67b4146aa7fad5b3889f808df12b110f230937
gcovr == 5.1 --hash=sha256:8bff85699d6a41057831bc3c201d9801d174da2800f8c403b0e6e831fe7936f3
lxml == 4.8.0 --hash=sha256:ce13d6291a5f47c1c8dbd375baa78551053bc6b5e5c0e9bb8e39c0a8359fd52f