Run a format-code pass on all files (#131)

This PR is the result of running "./scripts/format-code.ps1"
There are no manual changes in this PR

Signed-off-by: Dave Thaler <dthaler@ntdev.microsoft.com>
This commit is contained in:
Dave Thaler 2021-05-05 08:39:38 -07:00 коммит произвёл GitHub
Родитель a8045d4f3e
Коммит 00bd6ef2da
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
21 изменённых файлов: 401 добавлений и 391 удалений

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

@ -6,16 +6,17 @@
// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call,
LPVOID lpReserved) {
UNREFERENCED_PARAMETER(hModule);
UNREFERENCED_PARAMETER(lpReserved);
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
BOOL APIENTRY
DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
UNREFERENCED_PARAMETER(hModule);
UNREFERENCED_PARAMETER(lpReserved);
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

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

@ -2,7 +2,9 @@
// SPDX-License-Identifier: MIT
#pragma once
EbpfHelperPrototype get_helper_prototype_windows(unsigned int n);
bool is_helper_usable_windows(unsigned int n);
EbpfHelperPrototype
get_helper_prototype_windows(unsigned int n);
bool
is_helper_usable_windows(unsigned int n);
extern const ebpf_platform_t g_ebpf_platform_windows;

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

@ -119,8 +119,8 @@ verify_byte_code(
const char** error_message)
{
const ebpf_platform_t* platform = &g_ebpf_platform_windows;
std::vector<ebpf_inst> instructions{
(ebpf_inst*)byte_code, (ebpf_inst*)byte_code + byte_code_size / sizeof(ebpf_inst)};
std::vector<ebpf_inst> instructions{(ebpf_inst*)byte_code,
(ebpf_inst*)byte_code + byte_code_size / sizeof(ebpf_inst)};
program_info info{platform};
info.type = platform->get_program_type(section_name, path);
@ -167,12 +167,11 @@ ebpf_api_elf_enumerate_sections(
}
}
sequence.emplace_back(tlv_pack<tlv_sequence>(
{tlv_pack(raw_program.section.c_str()),
tlv_pack(raw_program.info.type.platform_specific_data),
tlv_pack(raw_program.info.map_descriptors.size()),
tlv_pack(convert_ebpf_program_to_bytes(raw_program.prog)),
tlv_pack(stats_sequence)}));
sequence.emplace_back(tlv_pack<tlv_sequence>({tlv_pack(raw_program.section.c_str()),
tlv_pack(raw_program.info.type.platform_specific_data),
tlv_pack(raw_program.info.map_descriptors.size()),
tlv_pack(convert_ebpf_program_to_bytes(raw_program.prog)),
tlv_pack(stats_sequence)}));
}
auto retval = tlv_pack(sequence);

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

@ -687,10 +687,9 @@ ebpf_api_get_next_map(ebpf_handle_t previous_handle, ebpf_handle_t* next_handle)
uint32_t
ebpf_api_get_next_program(ebpf_handle_t previous_handle, ebpf_handle_t* next_handle)
{
_ebpf_operation_get_next_program_request request{
sizeof(request),
ebpf_operation_id_t::EBPF_OPERATION_GET_NEXT_PROGRAM,
reinterpret_cast<uint64_t>(previous_handle)};
_ebpf_operation_get_next_program_request request{sizeof(request),
ebpf_operation_id_t::EBPF_OPERATION_GET_NEXT_PROGRAM,
reinterpret_cast<uint64_t>(previous_handle)};
_ebpf_operation_get_next_program_reply reply;

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

@ -5,21 +5,27 @@
#pragma once
namespace Platform {
BOOL DeviceIoControl(
_In_ ebpf_handle_t device_handle, uint32_t io_control_code,
_In_reads_bytes_opt_(input_buffer_size) void *input_buffer,
BOOL
DeviceIoControl(
_In_ ebpf_handle_t device_handle,
uint32_t io_control_code,
_In_reads_bytes_opt_(input_buffer_size) void* input_buffer,
uint32_t input_buffer_size,
_Out_writes_bytes_to_opt_(output_buffer_size,
*count_of_bytes_returned) void *output_buffer,
uint32_t output_buffer_size, _Out_opt_ uint32_t *count_of_bytes_returned,
_Inout_opt_ OVERLAPPED *overlapped);
_Out_writes_bytes_to_opt_(output_buffer_size, *count_of_bytes_returned) void* output_buffer,
uint32_t output_buffer_size,
_Out_opt_ uint32_t* count_of_bytes_returned,
_Inout_opt_ OVERLAPPED* overlapped);
ebpf_handle_t CreateFileW(_In_ PCWSTR file_name, uint32_t desired_access,
uint32_t share_mode,
_In_opt_ SECURITY_ATTRIBUTES *security_attributed,
uint32_t creation_disposition,
uint32_t flags_and_attributed,
_In_opt_ ebpf_handle_t template_file);
ebpf_handle_t
CreateFileW(
_In_ PCWSTR file_name,
uint32_t desired_access,
uint32_t share_mode,
_In_opt_ SECURITY_ATTRIBUTES* security_attributed,
uint32_t creation_disposition,
uint32_t flags_and_attributed,
_In_opt_ ebpf_handle_t template_file);
BOOL CloseHandle(_In_ _Post_ptr_invalid_ ebpf_handle_t handle);
BOOL
CloseHandle(_In_ _Post_ptr_invalid_ ebpf_handle_t handle);
} // namespace Platform

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

@ -33,11 +33,10 @@ _ebpf_core_map_update_element(ebpf_map_t* map, const uint8_t* key, const uint8_t
static void
_ebpf_core_map_delete_element(ebpf_map_t* map, const uint8_t* key);
static const void* _ebpf_program_helpers[] = {
NULL,
(void*)&_ebpf_core_map_find_element,
(void*)&_ebpf_core_map_update_element,
(void*)&_ebpf_core_map_delete_element};
static const void* _ebpf_program_helpers[] = {NULL,
(void*)&_ebpf_core_map_find_element,
(void*)&_ebpf_core_map_update_element,
(void*)&_ebpf_core_map_delete_element};
ebpf_error_code_t
ebpf_core_initiate()
@ -573,9 +572,9 @@ static ebpf_error_code_t
_ebpf_core_protocol_update_pinning(_In_ const struct _ebpf_operation_update_map_pinning_request* request)
{
ebpf_error_code_t retval;
const ebpf_utf8_string_t name = {
(uint8_t*)request->name,
request->header.length - EBPF_OFFSET_OF(ebpf_operation_update_pinning_request_t, name)};
const ebpf_utf8_string_t name = {(uint8_t*)request->name,
request->header.length -
EBPF_OFFSET_OF(ebpf_operation_update_pinning_request_t, name)};
ebpf_object_t* object = NULL;
if (name.length == 0) {

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

@ -17,19 +17,17 @@ typedef struct _process_entry
} process_entry_t;
#pragma clang section data = "maps"
bpf_map_def_t process_map = {
.size = sizeof(bpf_map_def_t),
.type = EBPF_MAP_TYPE_HASH,
.key_size = sizeof(uint64_t),
.value_size = sizeof(process_entry_t),
.max_entries = 1024};
bpf_map_def_t process_map = {.size = sizeof(bpf_map_def_t),
.type = EBPF_MAP_TYPE_HASH,
.key_size = sizeof(uint64_t),
.value_size = sizeof(process_entry_t),
.max_entries = 1024};
bpf_map_def_t limits_map = {
.size = sizeof(bpf_map_def_t),
.type = EBPF_MAP_TYPE_ARRAY,
.key_size = sizeof(uint32_t),
.value_size = sizeof(uint32_t),
.max_entries = 1};
bpf_map_def_t limits_map = {.size = sizeof(bpf_map_def_t),
.type = EBPF_MAP_TYPE_ARRAY,
.key_size = sizeof(uint32_t),
.value_size = sizeof(uint32_t),
.max_entries = 1};
inline void
copy_app_id(process_entry_t* entry, uint64_t start_index, char* begin, char* end)

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

@ -4,4 +4,8 @@
*/
#pragma clang section text = "xdp_prog"
int func() { return 42; }
int
func()
{
return 42;
}

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

@ -5,17 +5,22 @@
#pragma clang section text = "xdp_prog"
typedef int (*bpf_helper)(void *a, void *b, void *c, void *d);
typedef int (*bpf_helper)(void* a, void* b, void* c, void* d);
#define ebpf_map_lookup_elem ((bpf_helper)0)
#define ebpf_map_update_elem ((bpf_helper)1)
#define ebpf_map_delete_elem ((bpf_helper)2)
#define ebpf_get_tick_count ((bpf_helper)3)
typedef struct xdp_md {
unsigned char *data;
unsigned char *data_end;
unsigned char *data_meta;
typedef struct xdp_md
{
unsigned char* data;
unsigned char* data_end;
unsigned char* data_meta;
} xdp_md;
int func(xdp_md *ctx) { return ebpf_get_tick_count(ctx, 0, 0, 0); }
int
func(xdp_md* ctx)
{
return ebpf_get_tick_count(ctx, 0, 0, 0);
}

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

@ -11,12 +11,11 @@
#include "ebpf.h"
#pragma clang section data = "maps"
bpf_map_def_t test_map = {
.size = sizeof(bpf_map_def_t),
.type = EBPF_MAP_TYPE_ARRAY,
.key_size = sizeof(uint32_t),
.value_size = sizeof(uint32_t),
.max_entries = 1};
bpf_map_def_t test_map = {.size = sizeof(bpf_map_def_t),
.type = EBPF_MAP_TYPE_ARRAY,
.key_size = sizeof(uint32_t),
.value_size = sizeof(uint32_t),
.max_entries = 1};
#pragma clang section text = "xdp"
uint32_t

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

@ -18,24 +18,25 @@ bpf_map_def_t port_map = {.size = sizeof(bpf_map_def_t),
.max_entries = 1};
#pragma clang section text = "xdp"
int DropPacket(xdp_md_t *ctx) {
IPV4_HEADER *iphdr = (IPV4_HEADER *)ctx->data;
UDP_HEADER *udphdr = (UDP_HEADER *)(iphdr + 1);
int rc = 1;
if ((char *)ctx->data + sizeof(IPV4_HEADER) + sizeof(UDP_HEADER) >
(char *)ctx->data_end)
goto Done;
int
DropPacket(xdp_md_t* ctx)
{
IPV4_HEADER* iphdr = (IPV4_HEADER*)ctx->data;
UDP_HEADER* udphdr = (UDP_HEADER*)(iphdr + 1);
int rc = 1;
if ((char*)ctx->data + sizeof(IPV4_HEADER) + sizeof(UDP_HEADER) > (char*)ctx->data_end)
goto Done;
// udp
if (iphdr->Protocol == 17) {
if (ntohs(udphdr->length) <= sizeof(UDP_HEADER)) {
long key = 0;
long *count = ebpf_map_lookup_elem(&port_map, &key);
if (count)
*count = (*count + 1);
rc = 2;
// udp
if (iphdr->Protocol == 17) {
if (ntohs(udphdr->length) <= sizeof(UDP_HEADER)) {
long key = 0;
long* count = ebpf_map_lookup_elem(&port_map, &key);
if (count)
*count = (*count + 1);
rc = 2;
}
}
}
Done:
return rc;
return rc;
}

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

@ -69,12 +69,11 @@ typedef void (*ebpf_map_delete_elem_t)(bpf_map_def_t* map, void* key);
#define ebpf_map_delete_elem ((ebpf_map_delete_elem_t)3)
#pragma clang section data = "maps"
bpf_map_def_t test_map = {
.size = sizeof(bpf_map_def_t),
.type = EBPF_MAP_TYPE_HASH,
.key_size = sizeof(uint64_t),
.value_size = sizeof(uint64_t),
.max_entries = 1};
bpf_map_def_t test_map = {.size = sizeof(bpf_map_def_t),
.type = EBPF_MAP_TYPE_HASH,
.key_size = sizeof(uint64_t),
.value_size = sizeof(uint64_t),
.max_entries = 1};
#pragma clang section text = "bind"
int

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

@ -20,186 +20,167 @@
using std::string;
using std::vector;
static size_t hash(const raw_program &raw_prog) {
char *start = (char *)raw_prog.prog.data();
char *end = start + (raw_prog.prog.size() * sizeof(ebpf_inst));
return boost::hash_range(start, end);
static size_t
hash(const raw_program& raw_prog)
{
char* start = (char*)raw_prog.prog.data();
char* end = start + (raw_prog.prog.size() * sizeof(ebpf_inst));
return boost::hash_range(start, end);
}
int main(int argc, char **argv) {
ebpf_verifier_options_t ebpf_verifier_options = ebpf_verifier_default_options;
int
main(int argc, char** argv)
{
ebpf_verifier_options_t ebpf_verifier_options = ebpf_verifier_default_options;
// Parse command line arguments:
// Parse command line arguments:
crab::CrabEnableWarningMsg(false);
crab::CrabEnableWarningMsg(false);
CLI::App app{"A new eBPF verifier"};
CLI::App app{"A new eBPF verifier"};
std::string filename;
app.add_option("path", filename, "Elf file to analyze")
->required()
->type_name("FILE");
std::string filename;
app.add_option("path", filename, "Elf file to analyze")->required()->type_name("FILE");
std::string desired_section;
std::string desired_section;
app.add_option("section", desired_section, "Section to analyze")
->type_name("SECTION");
bool list = false;
app.add_flag("-l", list, "List sections");
app.add_option("section", desired_section, "Section to analyze")->type_name("SECTION");
bool list = false;
app.add_flag("-l", list, "List sections");
std::string platform_name = "linux";
std::set<string> platform_names{"linux", "windows"};
app.add_set("-p,--plat,--platform", platform_name, platform_names, "Platform")
->type_name("PLATFORM");
std::string platform_name = "linux";
std::set<string> platform_names{"linux", "windows"};
app.add_set("-p,--plat,--platform", platform_name, platform_names, "Platform")->type_name("PLATFORM");
std::string domain = "zoneCrab";
std::set<string> doms{"stats", "linux", "zoneCrab", "cfg"};
app.add_set("-d,--dom,--domain", domain, doms, "Abstract domain")
->type_name("DOMAIN");
std::string domain = "zoneCrab";
std::set<string> doms{"stats", "linux", "zoneCrab", "cfg"};
app.add_set("-d,--dom,--domain", domain, doms, "Abstract domain")->type_name("DOMAIN");
ebpf_verifier_options.check_termination = false;
app.add_flag("--termination", ebpf_verifier_options.check_termination,
"Verify termination");
ebpf_verifier_options.check_termination = false;
app.add_flag("--termination", ebpf_verifier_options.check_termination, "Verify termination");
bool verbose = false;
app.add_flag("-i", ebpf_verifier_options.print_invariants,
"Print invariants");
app.add_flag("-f", ebpf_verifier_options.print_failures,
"Print verifier's failure logs");
app.add_flag("-v", verbose, "Print both invariants and failures");
app.add_flag("--no-simplify", ebpf_verifier_options.no_simplify,
"Do not simplify");
bool verbose = false;
app.add_flag("-i", ebpf_verifier_options.print_invariants, "Print invariants");
app.add_flag("-f", ebpf_verifier_options.print_failures, "Print verifier's failure logs");
app.add_flag("-v", verbose, "Print both invariants and failures");
app.add_flag("--no-simplify", ebpf_verifier_options.no_simplify, "Do not simplify");
bool no_mock_maps{false};
app.add_flag("--no-mock-maps", no_mock_maps, "Use actual maps");
bool no_mock_maps{false};
app.add_flag("--no-mock-maps", no_mock_maps, "Use actual maps");
std::string asmfile;
app.add_option("--asm", asmfile, "Print disassembly to FILE")
->type_name("FILE");
std::string dotfile;
app.add_option("--dot", dotfile, "Export control-flow graph to dot FILE")
->type_name("FILE");
std::string asmfile;
app.add_option("--asm", asmfile, "Print disassembly to FILE")->type_name("FILE");
std::string dotfile;
app.add_option("--dot", dotfile, "Export control-flow graph to dot FILE")->type_name("FILE");
app.footer("You can use @headers as the path to instead just show the output "
"field headers.\n");
app.footer("You can use @headers as the path to instead just show the output "
"field headers.\n");
CLI11_PARSE(app, argc, argv);
if (verbose)
ebpf_verifier_options.print_invariants =
ebpf_verifier_options.print_failures = true;
CLI11_PARSE(app, argc, argv);
if (verbose)
ebpf_verifier_options.print_invariants = ebpf_verifier_options.print_failures = true;
// Main program
// Main program
if (filename == "@headers") {
if (domain == "stats") {
std::cout << "hash";
std::cout << ",instructions";
for (const string &h : stats_headers()) {
std::cout << "," << h;
}
} else {
std::cout << domain << "?,";
std::cout << domain << "_sec,";
std::cout << domain << "_kb";
if (filename == "@headers") {
if (domain == "stats") {
std::cout << "hash";
std::cout << ",instructions";
for (const string& h : stats_headers()) {
std::cout << "," << h;
}
} else {
std::cout << domain << "?,";
std::cout << domain << "_sec,";
std::cout << domain << "_kb";
}
std::cout << "\n";
return 0;
}
std::cout << "\n";
return 0;
}
#if !__linux__
if (domain == "linux") {
std::cerr << "error: linux domain is unsupported on this machine\n";
return 64;
}
if (domain == "linux") {
std::cerr << "error: linux domain is unsupported on this machine\n";
return 64;
}
#endif
if (no_mock_maps || (domain == "linux"))
ebpf_verifier_options.mock_map_fds = false;
const ebpf_platform_t *platform = (platform_name == "linux")
? &g_ebpf_platform_linux
: &g_ebpf_platform_windows;
if (no_mock_maps || (domain == "linux"))
ebpf_verifier_options.mock_map_fds = false;
const ebpf_platform_t* platform = (platform_name == "linux") ? &g_ebpf_platform_linux : &g_ebpf_platform_windows;
// Read a set of raw program sections from an ELF file.
vector<raw_program> raw_progs;
try {
raw_progs =
read_elf(filename, desired_section, &ebpf_verifier_options, platform);
} catch (std::runtime_error e) {
std::cerr << "error: " << e.what() << std::endl;
return 1;
}
if (list || raw_progs.size() != 1) {
if (!list) {
std::cout << "please specify a section\n";
std::cout << "available sections:\n";
// Read a set of raw program sections from an ELF file.
vector<raw_program> raw_progs;
try {
raw_progs = read_elf(filename, desired_section, &ebpf_verifier_options, platform);
} catch (std::runtime_error e) {
std::cerr << "error: " << e.what() << std::endl;
return 1;
}
if (!desired_section.empty() && raw_progs.size() == 0) {
// We could not find the desired section, so get the full list
// of possibilities.
raw_progs =
read_elf(filename, string(), &ebpf_verifier_options, platform);
if (list || raw_progs.size() != 1) {
if (!list) {
std::cout << "please specify a section\n";
std::cout << "available sections:\n";
}
if (!desired_section.empty() && raw_progs.size() == 0) {
// We could not find the desired section, so get the full list
// of possibilities.
raw_progs = read_elf(filename, string(), &ebpf_verifier_options, platform);
}
for (const raw_program& raw_prog : raw_progs) {
std::cout << raw_prog.section << " ";
}
std::cout << "\n";
return list ? 0 : 64;
}
for (const raw_program &raw_prog : raw_progs) {
std::cout << raw_prog.section << " ";
// Select the last program section.
raw_program raw_prog = raw_progs.back();
// Convert the raw program section to a set of instructions.
std::variant<InstructionSeq, std::string> prog_or_error = unmarshal(raw_prog, platform);
if (std::holds_alternative<string>(prog_or_error)) {
std::cout << "unmarshaling error at " << std::get<string>(prog_or_error) << "\n";
return 1;
}
std::cout << "\n";
return list ? 0 : 64;
}
// Select the last program section.
raw_program raw_prog = raw_progs.back();
// Convert the raw program section to a set of instructions.
std::variant<InstructionSeq, std::string> prog_or_error =
unmarshal(raw_prog, platform);
if (std::holds_alternative<string>(prog_or_error)) {
std::cout << "unmarshaling error at " << std::get<string>(prog_or_error)
<< "\n";
return 1;
}
auto &prog = std::get<InstructionSeq>(prog_or_error);
if (!asmfile.empty()) {
print(prog, asmfile);
}
if (domain == "zoneCrab") {
const auto [res, seconds] = timed_execution([&] {
return ebpf_verify_program(std::cout, prog, raw_prog.info,
&ebpf_verifier_options);
});
std::cout << res << "," << seconds << "," << resident_set_size_kb() << "\n";
return !res;
} else if (domain == "linux") {
// Pass the intruction sequence to the Linux kernel verifier.
const auto [res, seconds] = bpf_verify_program(
raw_prog.info.type, raw_prog.prog, &ebpf_verifier_options);
std::cout << res << "," << seconds << "," << resident_set_size_kb() << "\n";
return !res;
} else if (domain == "stats") {
// Convert the instruction sequence to a control-flow graph.
cfg_t cfg =
prepare_cfg(prog, raw_prog.info, !ebpf_verifier_options.no_simplify);
// Just print eBPF program stats.
auto stats = collect_stats(cfg);
if (!dotfile.empty()) {
print_dot(cfg, dotfile);
auto& prog = std::get<InstructionSeq>(prog_or_error);
if (!asmfile.empty()) {
print(prog, asmfile);
}
std::cout << std::hex << hash(raw_prog) << std::dec << "," << prog.size();
for (const string &h : stats_headers()) {
std::cout << "," << stats.at(h);
if (domain == "zoneCrab") {
const auto [res, seconds] = timed_execution(
[&] { return ebpf_verify_program(std::cout, prog, raw_prog.info, &ebpf_verifier_options); });
std::cout << res << "," << seconds << "," << resident_set_size_kb() << "\n";
return !res;
} else if (domain == "linux") {
// Pass the intruction sequence to the Linux kernel verifier.
const auto [res, seconds] = bpf_verify_program(raw_prog.info.type, raw_prog.prog, &ebpf_verifier_options);
std::cout << res << "," << seconds << "," << resident_set_size_kb() << "\n";
return !res;
} else if (domain == "stats") {
// Convert the instruction sequence to a control-flow graph.
cfg_t cfg = prepare_cfg(prog, raw_prog.info, !ebpf_verifier_options.no_simplify);
// Just print eBPF program stats.
auto stats = collect_stats(cfg);
if (!dotfile.empty()) {
print_dot(cfg, dotfile);
}
std::cout << std::hex << hash(raw_prog) << std::dec << "," << prog.size();
for (const string& h : stats_headers()) {
std::cout << "," << stats.at(h);
}
std::cout << "\n";
} else if (domain == "cfg") {
// Convert the instruction sequence to a control-flow graph.
cfg_t cfg = prepare_cfg(prog, raw_prog.info, !ebpf_verifier_options.no_simplify);
std::cout << cfg;
std::cout << "\n";
} else {
assert(false);
}
std::cout << "\n";
} else if (domain == "cfg") {
// Convert the instruction sequence to a control-flow graph.
cfg_t cfg =
prepare_cfg(prog, raw_prog.info, !ebpf_verifier_options.no_simplify);
std::cout << cfg;
std::cout << "\n";
} else {
assert(false);
}
return 0;
return 0;
}

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

@ -13,101 +13,103 @@ using std::string;
using std::vector;
// Section name MUST indicate the program type.
static BpfProgType section_to_progtype(const std::string &section) {
if (section.find("xdp") != std::string::npos)
return BpfProgType::XDP;
return BpfProgType::UNSPEC;
static BpfProgType
section_to_progtype(const std::string& section)
{
if (section.find("xdp") != std::string::npos)
return BpfProgType::XDP;
return BpfProgType::UNSPEC;
}
// template <typename T>
static vector<char> vector_of(ELFIO::section *sec) {
if (!sec)
return {};
auto data = sec->get_data();
auto size = sec->get_size();
// assert(size % sizeof(T) == 0);
return {(char *)data, (char *)(data + size)};
static vector<char>
vector_of(ELFIO::section* sec)
{
if (!sec)
return {};
auto data = sec->get_data();
auto size = sec->get_size();
// assert(size % sizeof(T) == 0);
return {(char*)data, (char*)(data + size)};
}
vector<raw_program> read_elf(const std::string &path,
const std::string &desired_section) {
ELFIO::elfio reader;
if (!reader.load(path)) {
throw std::runtime_error(string("Can't find or process ELF file ") + path);
}
vector<raw_program> res;
program_info info;
// Go through the sections to find the required secion.
// Extract the instructions to be passed to the jitter.
for (const auto section : reader.sections) {
const string name = section->get_name();
std::cout << "section " << name << endl;
if (!desired_section.empty() && name != desired_section)
continue;
if (name == "license" || name == "version" || name == "maps")
continue;
if (name != ".text" && name.find('.') == 0) {
continue;
vector<raw_program>
read_elf(const std::string& path, const std::string& desired_section)
{
ELFIO::elfio reader;
if (!reader.load(path)) {
throw std::runtime_error(string("Can't find or process ELF file ") + path);
}
info.program_type = section_to_progtype(name);
if (section->get_size() == 0)
continue;
raw_program prog{path, name, vector_of(section), info};
vector<raw_program> res;
program_info info;
res.push_back(prog);
}
// Go through the sections to find the required secion.
// Extract the instructions to be passed to the jitter.
for (const auto section : reader.sections) {
const string name = section->get_name();
std::cout << "section " << name << endl;
if (res.empty()) {
throw std::runtime_error(string("Can't find section ") + desired_section +
" in file " + path);
}
return res;
}
int __cdecl main(int argc, char **argv) {
CLI::App app{"Elf Reader"};
std::string filename;
app.add_option("path", filename, "Path to elf file")
->required()
->type_name("FILE");
std::string desired_section;
app.add_option("section", desired_section, "Section name")
->type_name("SECTION");
bool list = false;
app.add_flag("-l", list, "List sections");
CLI11_PARSE(app, argc, argv);
// load elf file
vector<raw_program> raw_progs = read_elf(filename, desired_section);
// Print out the sections
if (list || raw_progs.size() != 1) {
// sections
for (const raw_program &raw_prog : raw_progs) {
std::cout << raw_prog.section << " ";
// raw instructions
if (raw_prog.section == ".text") {
int count = 0;
std::cout << endl;
for (char inst : raw_prog.prog) {
std::cout << " 0x" << std::hex << (int)inst;
// new line after 8 bytes
if (count++ == 7) {
std::cout << endl;
count = 0;
}
if (!desired_section.empty() && name != desired_section)
continue;
if (name == "license" || name == "version" || name == "maps")
continue;
if (name != ".text" && name.find('.') == 0) {
continue;
}
}
info.program_type = section_to_progtype(name);
if (section->get_size() == 0)
continue;
raw_program prog{path, name, vector_of(section), info};
res.push_back(prog);
}
std::cout << endl;
}
return 0;
if (res.empty()) {
throw std::runtime_error(string("Can't find section ") + desired_section + " in file " + path);
}
return res;
}
int __cdecl main(int argc, char** argv)
{
CLI::App app{"Elf Reader"};
std::string filename;
app.add_option("path", filename, "Path to elf file")->required()->type_name("FILE");
std::string desired_section;
app.add_option("section", desired_section, "Section name")->type_name("SECTION");
bool list = false;
app.add_flag("-l", list, "List sections");
CLI11_PARSE(app, argc, argv);
// load elf file
vector<raw_program> raw_progs = read_elf(filename, desired_section);
// Print out the sections
if (list || raw_progs.size() != 1) {
// sections
for (const raw_program& raw_prog : raw_progs) {
std::cout << raw_prog.section << " ";
// raw instructions
if (raw_prog.section == ".text") {
int count = 0;
std::cout << endl;
for (char inst : raw_prog.prog) {
std::cout << " 0x" << std::hex << (int)inst;
// new line after 8 bytes
if (count++ == 7) {
std::cout << endl;
count = 0;
}
}
}
}
std::cout << endl;
}
return 0;
}

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

@ -6,46 +6,60 @@
using namespace std;
// ebpf instruction schema
struct ebpf_inst {
uint8_t opcode;
uint8_t dst : 4; //< Destination register
uint8_t src : 4; //< Source register
int16_t offset;
int32_t imm; //< Immediate constant
struct ebpf_inst
{
uint8_t opcode;
uint8_t dst : 4; //< Destination register
uint8_t src : 4; //< Source register
int16_t offset;
int32_t imm; //< Immediate constant
};
enum class BpfProgType : int { UNSPEC, XDP };
enum class MapType : unsigned int { UNSPEC, HASH, ARRAY };
struct map_def {
int original_fd;
MapType type;
unsigned int key_size;
unsigned int value_size;
unsigned int inner_map_fd;
enum class BpfProgType : int
{
UNSPEC,
XDP
};
struct ptype_descr {
int size{};
int data = -1;
int end = -1;
int meta = -1; // data to meta is like end to data. i.e. meta <= data <= end
enum class MapType : unsigned int
{
UNSPEC,
HASH,
ARRAY
};
struct program_info {
BpfProgType program_type;
std::vector<map_def> map_defs;
ptype_descr descriptor;
struct map_def
{
int original_fd;
MapType type;
unsigned int key_size;
unsigned int value_size;
unsigned int inner_map_fd;
};
struct ptype_descr
{
int size{};
int data = -1;
int end = -1;
int meta = -1; // data to meta is like end to data. i.e. meta <= data <= end
};
struct program_info
{
BpfProgType program_type;
std::vector<map_def> map_defs;
ptype_descr descriptor;
};
extern program_info global_program_info;
struct raw_program {
std::string filename;
std::string section;
std::vector<char> prog;
program_info info;
struct raw_program
{
std::string filename;
std::string section;
std::vector<char> prog;
program_info info;
};
constexpr int xdp_regions = 5 * 4;

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

@ -3,12 +3,13 @@
#pragma once
#ifdef __cplusplus
extern "C" {
extern "C"
{
#endif
FN_HANDLE_CMD handle_ebpf_show_disassembly;
FN_HANDLE_CMD handle_ebpf_show_sections;
FN_HANDLE_CMD handle_ebpf_show_verification;
FN_HANDLE_CMD handle_ebpf_show_disassembly;
FN_HANDLE_CMD handle_ebpf_show_sections;
FN_HANDLE_CMD handle_ebpf_show_verification;
#ifdef __cplusplus
}

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

@ -63,12 +63,11 @@ handle_ebpf_add_program(
UNREFERENCED_PARAMETER(data);
UNREFERENCED_PARAMETER(done);
TAG_TYPE tags[] = {
{TOKEN_FILENAME, NS_REQ_PRESENT, FALSE},
{TOKEN_SECTION, NS_REQ_ZERO, FALSE},
{TOKEN_TYPE, NS_REQ_ZERO, FALSE},
{TOKEN_PINNED, NS_REQ_ZERO, FALSE},
{TOKEN_EXECUTION, NS_REQ_ZERO, FALSE}};
TAG_TYPE tags[] = {{TOKEN_FILENAME, NS_REQ_PRESENT, FALSE},
{TOKEN_SECTION, NS_REQ_ZERO, FALSE},
{TOKEN_TYPE, NS_REQ_ZERO, FALSE},
{TOKEN_PINNED, NS_REQ_ZERO, FALSE},
{TOKEN_EXECUTION, NS_REQ_ZERO, FALSE}};
ULONG tag_type[_countof(tags)] = {0};
ULONG status =

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

@ -3,13 +3,14 @@
#pragma once
#ifdef __cplusplus
extern "C" {
extern "C"
{
#endif
FN_HANDLE_CMD handle_ebpf_add_program;
FN_HANDLE_CMD handle_ebpf_delete_program;
FN_HANDLE_CMD handle_ebpf_set_program;
FN_HANDLE_CMD handle_ebpf_show_programs;
FN_HANDLE_CMD handle_ebpf_add_program;
FN_HANDLE_CMD handle_ebpf_delete_program;
FN_HANDLE_CMD handle_ebpf_set_program;
FN_HANDLE_CMD handle_ebpf_show_programs;
#ifdef __cplusplus
}

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

@ -9,9 +9,10 @@
#define TOKEN_TYPE L"type"
#define TOKEN_EXECUTION L"execution"
typedef enum {
VL_NORMAL = 0,
VL_VERBOSE = 1,
typedef enum
{
VL_NORMAL = 0,
VL_VERBOSE = 1,
} VERBOSITY_LEVEL;
extern TOKEN_VALUE g_LevelEnum[2];

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

@ -151,11 +151,10 @@ struct
const char* name;
const char* help;
operation_t operation;
} commands[]{
{"load", "load\tLoad the port quota eBPF program", load},
{"unload", "unload\tUnload the port quota eBPF program", unload},
{"stats", "stats\tShow stats from the port quota eBPF program", stats},
{"limit", "limit value\tSet the port quota limit", limit}};
} commands[]{{"load", "load\tLoad the port quota eBPF program", load},
{"unload", "unload\tUnload the port quota eBPF program", unload},
{"stats", "stats\tShow stats from the port quota eBPF program", stats},
{"limit", "limit value\tSet the port quota limit", limit}};
void
print_usage(char* path)