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. // dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h" #include "pch.h"
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, BOOL APIENTRY
LPVOID lpReserved) { DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
UNREFERENCED_PARAMETER(hModule); {
UNREFERENCED_PARAMETER(lpReserved); UNREFERENCED_PARAMETER(hModule);
switch (ul_reason_for_call) { UNREFERENCED_PARAMETER(lpReserved);
case DLL_PROCESS_ATTACH: switch (ul_reason_for_call) {
case DLL_THREAD_ATTACH: case DLL_PROCESS_ATTACH:
case DLL_THREAD_DETACH: case DLL_THREAD_ATTACH:
case DLL_PROCESS_DETACH: case DLL_THREAD_DETACH:
break; case DLL_PROCESS_DETACH:
} break;
return TRUE; }
return TRUE;
} }

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

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

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

@ -119,8 +119,8 @@ verify_byte_code(
const char** error_message) const char** error_message)
{ {
const ebpf_platform_t* platform = &g_ebpf_platform_windows; const ebpf_platform_t* platform = &g_ebpf_platform_windows;
std::vector<ebpf_inst> instructions{ std::vector<ebpf_inst> instructions{(ebpf_inst*)byte_code,
(ebpf_inst*)byte_code, (ebpf_inst*)byte_code + byte_code_size / sizeof(ebpf_inst)}; (ebpf_inst*)byte_code + byte_code_size / sizeof(ebpf_inst)};
program_info info{platform}; program_info info{platform};
info.type = platform->get_program_type(section_name, path); 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>( sequence.emplace_back(tlv_pack<tlv_sequence>({tlv_pack(raw_program.section.c_str()),
{tlv_pack(raw_program.section.c_str()), tlv_pack(raw_program.info.type.platform_specific_data),
tlv_pack(raw_program.info.type.platform_specific_data), tlv_pack(raw_program.info.map_descriptors.size()),
tlv_pack(raw_program.info.map_descriptors.size()), tlv_pack(convert_ebpf_program_to_bytes(raw_program.prog)),
tlv_pack(convert_ebpf_program_to_bytes(raw_program.prog)), tlv_pack(stats_sequence)}));
tlv_pack(stats_sequence)}));
} }
auto retval = tlv_pack(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 uint32_t
ebpf_api_get_next_program(ebpf_handle_t previous_handle, ebpf_handle_t* next_handle) ebpf_api_get_next_program(ebpf_handle_t previous_handle, ebpf_handle_t* next_handle)
{ {
_ebpf_operation_get_next_program_request request{ _ebpf_operation_get_next_program_request request{sizeof(request),
sizeof(request), ebpf_operation_id_t::EBPF_OPERATION_GET_NEXT_PROGRAM,
ebpf_operation_id_t::EBPF_OPERATION_GET_NEXT_PROGRAM, reinterpret_cast<uint64_t>(previous_handle)};
reinterpret_cast<uint64_t>(previous_handle)};
_ebpf_operation_get_next_program_reply reply; _ebpf_operation_get_next_program_reply reply;

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

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

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

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

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

@ -17,19 +17,17 @@ typedef struct _process_entry
} process_entry_t; } process_entry_t;
#pragma clang section data = "maps" #pragma clang section data = "maps"
bpf_map_def_t process_map = { bpf_map_def_t process_map = {.size = sizeof(bpf_map_def_t),
.size = sizeof(bpf_map_def_t), .type = EBPF_MAP_TYPE_HASH,
.type = EBPF_MAP_TYPE_HASH, .key_size = sizeof(uint64_t),
.key_size = sizeof(uint64_t), .value_size = sizeof(process_entry_t),
.value_size = sizeof(process_entry_t), .max_entries = 1024};
.max_entries = 1024};
bpf_map_def_t limits_map = { bpf_map_def_t limits_map = {.size = sizeof(bpf_map_def_t),
.size = sizeof(bpf_map_def_t), .type = EBPF_MAP_TYPE_ARRAY,
.type = EBPF_MAP_TYPE_ARRAY, .key_size = sizeof(uint32_t),
.key_size = sizeof(uint32_t), .value_size = sizeof(uint32_t),
.value_size = sizeof(uint32_t), .max_entries = 1};
.max_entries = 1};
inline void inline void
copy_app_id(process_entry_t* entry, uint64_t start_index, char* begin, char* end) 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" #pragma clang section text = "xdp_prog"
int func() { return 42; } int
func()
{
return 42;
}

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

@ -5,17 +5,22 @@
#pragma clang section text = "xdp_prog" #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_lookup_elem ((bpf_helper)0)
#define ebpf_map_update_elem ((bpf_helper)1) #define ebpf_map_update_elem ((bpf_helper)1)
#define ebpf_map_delete_elem ((bpf_helper)2) #define ebpf_map_delete_elem ((bpf_helper)2)
#define ebpf_get_tick_count ((bpf_helper)3) #define ebpf_get_tick_count ((bpf_helper)3)
typedef struct xdp_md { typedef struct xdp_md
unsigned char *data; {
unsigned char *data_end; unsigned char* data;
unsigned char *data_meta; unsigned char* data_end;
unsigned char* data_meta;
} xdp_md; } 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" #include "ebpf.h"
#pragma clang section data = "maps" #pragma clang section data = "maps"
bpf_map_def_t test_map = { bpf_map_def_t test_map = {.size = sizeof(bpf_map_def_t),
.size = sizeof(bpf_map_def_t), .type = EBPF_MAP_TYPE_ARRAY,
.type = EBPF_MAP_TYPE_ARRAY, .key_size = sizeof(uint32_t),
.key_size = sizeof(uint32_t), .value_size = sizeof(uint32_t),
.value_size = sizeof(uint32_t), .max_entries = 1};
.max_entries = 1};
#pragma clang section text = "xdp" #pragma clang section text = "xdp"
uint32_t uint32_t

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

@ -18,24 +18,25 @@ bpf_map_def_t port_map = {.size = sizeof(bpf_map_def_t),
.max_entries = 1}; .max_entries = 1};
#pragma clang section text = "xdp" #pragma clang section text = "xdp"
int DropPacket(xdp_md_t *ctx) { int
IPV4_HEADER *iphdr = (IPV4_HEADER *)ctx->data; DropPacket(xdp_md_t* ctx)
UDP_HEADER *udphdr = (UDP_HEADER *)(iphdr + 1); {
int rc = 1; IPV4_HEADER* iphdr = (IPV4_HEADER*)ctx->data;
if ((char *)ctx->data + sizeof(IPV4_HEADER) + sizeof(UDP_HEADER) > UDP_HEADER* udphdr = (UDP_HEADER*)(iphdr + 1);
(char *)ctx->data_end) int rc = 1;
goto Done; if ((char*)ctx->data + sizeof(IPV4_HEADER) + sizeof(UDP_HEADER) > (char*)ctx->data_end)
goto Done;
// udp // udp
if (iphdr->Protocol == 17) { if (iphdr->Protocol == 17) {
if (ntohs(udphdr->length) <= sizeof(UDP_HEADER)) { if (ntohs(udphdr->length) <= sizeof(UDP_HEADER)) {
long key = 0; long key = 0;
long *count = ebpf_map_lookup_elem(&port_map, &key); long* count = ebpf_map_lookup_elem(&port_map, &key);
if (count) if (count)
*count = (*count + 1); *count = (*count + 1);
rc = 2; rc = 2;
}
} }
}
Done: 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) #define ebpf_map_delete_elem ((ebpf_map_delete_elem_t)3)
#pragma clang section data = "maps" #pragma clang section data = "maps"
bpf_map_def_t test_map = { bpf_map_def_t test_map = {.size = sizeof(bpf_map_def_t),
.size = sizeof(bpf_map_def_t), .type = EBPF_MAP_TYPE_HASH,
.type = EBPF_MAP_TYPE_HASH, .key_size = sizeof(uint64_t),
.key_size = sizeof(uint64_t), .value_size = sizeof(uint64_t),
.value_size = sizeof(uint64_t), .max_entries = 1};
.max_entries = 1};
#pragma clang section text = "bind" #pragma clang section text = "bind"
int int

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

@ -20,186 +20,167 @@
using std::string; using std::string;
using std::vector; using std::vector;
static size_t hash(const raw_program &raw_prog) { static size_t
char *start = (char *)raw_prog.prog.data(); hash(const raw_program& raw_prog)
char *end = start + (raw_prog.prog.size() * sizeof(ebpf_inst)); {
return boost::hash_range(start, end); 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) { int
ebpf_verifier_options_t ebpf_verifier_options = ebpf_verifier_default_options; 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; std::string filename;
app.add_option("path", filename, "Elf file to analyze") app.add_option("path", filename, "Elf file to analyze")->required()->type_name("FILE");
->required()
->type_name("FILE");
std::string desired_section; std::string desired_section;
app.add_option("section", desired_section, "Section to analyze") app.add_option("section", desired_section, "Section to analyze")->type_name("SECTION");
->type_name("SECTION"); bool list = false;
bool list = false; app.add_flag("-l", list, "List sections");
app.add_flag("-l", list, "List sections");
std::string platform_name = "linux"; std::string platform_name = "linux";
std::set<string> platform_names{"linux", "windows"}; std::set<string> platform_names{"linux", "windows"};
app.add_set("-p,--plat,--platform", platform_name, platform_names, "Platform") app.add_set("-p,--plat,--platform", platform_name, platform_names, "Platform")->type_name("PLATFORM");
->type_name("PLATFORM");
std::string domain = "zoneCrab"; std::string domain = "zoneCrab";
std::set<string> doms{"stats", "linux", "zoneCrab", "cfg"}; std::set<string> doms{"stats", "linux", "zoneCrab", "cfg"};
app.add_set("-d,--dom,--domain", domain, doms, "Abstract domain") app.add_set("-d,--dom,--domain", domain, doms, "Abstract domain")->type_name("DOMAIN");
->type_name("DOMAIN");
ebpf_verifier_options.check_termination = false; ebpf_verifier_options.check_termination = false;
app.add_flag("--termination", ebpf_verifier_options.check_termination, app.add_flag("--termination", ebpf_verifier_options.check_termination, "Verify termination");
"Verify termination");
bool verbose = false; bool verbose = false;
app.add_flag("-i", ebpf_verifier_options.print_invariants, app.add_flag("-i", ebpf_verifier_options.print_invariants, "Print invariants");
"Print invariants"); app.add_flag("-f", ebpf_verifier_options.print_failures, "Print verifier's failure logs");
app.add_flag("-f", ebpf_verifier_options.print_failures, app.add_flag("-v", verbose, "Print both invariants and failures");
"Print verifier's failure logs"); app.add_flag("--no-simplify", ebpf_verifier_options.no_simplify, "Do not simplify");
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}; bool no_mock_maps{false};
app.add_flag("--no-mock-maps", no_mock_maps, "Use actual maps"); app.add_flag("--no-mock-maps", no_mock_maps, "Use actual maps");
std::string asmfile; std::string asmfile;
app.add_option("--asm", asmfile, "Print disassembly to FILE") app.add_option("--asm", asmfile, "Print disassembly to FILE")->type_name("FILE");
->type_name("FILE"); std::string dotfile;
std::string dotfile; app.add_option("--dot", dotfile, "Export control-flow graph to dot FILE")->type_name("FILE");
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 " app.footer("You can use @headers as the path to instead just show the output "
"field headers.\n"); "field headers.\n");
CLI11_PARSE(app, argc, argv); CLI11_PARSE(app, argc, argv);
if (verbose) if (verbose)
ebpf_verifier_options.print_invariants = ebpf_verifier_options.print_invariants = ebpf_verifier_options.print_failures = true;
ebpf_verifier_options.print_failures = true;
// Main program // Main program
if (filename == "@headers") { if (filename == "@headers") {
if (domain == "stats") { if (domain == "stats") {
std::cout << "hash"; std::cout << "hash";
std::cout << ",instructions"; std::cout << ",instructions";
for (const string &h : stats_headers()) { for (const string& h : stats_headers()) {
std::cout << "," << h; std::cout << "," << h;
} }
} else { } else {
std::cout << domain << "?,"; std::cout << domain << "?,";
std::cout << domain << "_sec,"; std::cout << domain << "_sec,";
std::cout << domain << "_kb"; std::cout << domain << "_kb";
}
std::cout << "\n";
return 0;
} }
std::cout << "\n";
return 0;
}
#if !__linux__ #if !__linux__
if (domain == "linux") { if (domain == "linux") {
std::cerr << "error: linux domain is unsupported on this machine\n"; std::cerr << "error: linux domain is unsupported on this machine\n";
return 64; return 64;
} }
#endif #endif
if (no_mock_maps || (domain == "linux")) if (no_mock_maps || (domain == "linux"))
ebpf_verifier_options.mock_map_fds = false; ebpf_verifier_options.mock_map_fds = false;
const ebpf_platform_t *platform = (platform_name == "linux") const ebpf_platform_t* platform = (platform_name == "linux") ? &g_ebpf_platform_linux : &g_ebpf_platform_windows;
? &g_ebpf_platform_linux
: &g_ebpf_platform_windows;
// Read a set of raw program sections from an ELF file. // Read a set of raw program sections from an ELF file.
vector<raw_program> raw_progs; vector<raw_program> raw_progs;
try { try {
raw_progs = raw_progs = read_elf(filename, desired_section, &ebpf_verifier_options, platform);
read_elf(filename, desired_section, &ebpf_verifier_options, platform); } catch (std::runtime_error e) {
} catch (std::runtime_error e) { std::cerr << "error: " << e.what() << std::endl;
std::cerr << "error: " << e.what() << std::endl; return 1;
return 1;
}
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 if (list || raw_progs.size() != 1) {
// of possibilities. if (!list) {
raw_progs = std::cout << "please specify a section\n";
read_elf(filename, string(), &ebpf_verifier_options, platform); 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. auto& prog = std::get<InstructionSeq>(prog_or_error);
raw_program raw_prog = raw_progs.back(); if (!asmfile.empty()) {
print(prog, asmfile);
// 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);
} }
std::cout << std::hex << hash(raw_prog) << std::dec << "," << prog.size();
for (const string &h : stats_headers()) { if (domain == "zoneCrab") {
std::cout << "," << stats.at(h); 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"; return 0;
} 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;
} }

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

@ -13,101 +13,103 @@ using std::string;
using std::vector; using std::vector;
// Section name MUST indicate the program type. // Section name MUST indicate the program type.
static BpfProgType section_to_progtype(const std::string &section) { static BpfProgType
if (section.find("xdp") != std::string::npos) section_to_progtype(const std::string& section)
return BpfProgType::XDP; {
return BpfProgType::UNSPEC; if (section.find("xdp") != std::string::npos)
return BpfProgType::XDP;
return BpfProgType::UNSPEC;
} }
// template <typename T> // template <typename T>
static vector<char> vector_of(ELFIO::section *sec) { static vector<char>
if (!sec) vector_of(ELFIO::section* sec)
return {}; {
auto data = sec->get_data(); if (!sec)
auto size = sec->get_size(); return {};
// assert(size % sizeof(T) == 0); auto data = sec->get_data();
return {(char *)data, (char *)(data + size)}; 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, vector<raw_program>
const std::string &desired_section) { read_elf(const std::string& path, const std::string& desired_section)
ELFIO::elfio reader; {
if (!reader.load(path)) { ELFIO::elfio reader;
throw std::runtime_error(string("Can't find or process ELF file ") + path); 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;
} }
info.program_type = section_to_progtype(name);
if (section->get_size() == 0) vector<raw_program> res;
continue; program_info info;
raw_program prog{path, name, vector_of(section), 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()) { if (!desired_section.empty() && name != desired_section)
throw std::runtime_error(string("Can't find section ") + desired_section + continue;
" in file " + path); if (name == "license" || name == "version" || name == "maps")
} continue;
return res; if (name != ".text" && name.find('.') == 0) {
} continue;
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;
}
} }
} 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;
} if (res.empty()) {
return 0; 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; using namespace std;
// ebpf instruction schema // ebpf instruction schema
struct ebpf_inst { struct ebpf_inst
uint8_t opcode; {
uint8_t dst : 4; //< Destination register uint8_t opcode;
uint8_t src : 4; //< Source register uint8_t dst : 4; //< Destination register
int16_t offset; uint8_t src : 4; //< Source register
int32_t imm; //< Immediate constant int16_t offset;
int32_t imm; //< Immediate constant
}; };
enum class BpfProgType : int { UNSPEC, XDP }; enum class BpfProgType : int
{
enum class MapType : unsigned int { UNSPEC, HASH, ARRAY }; UNSPEC,
XDP
struct map_def {
int original_fd;
MapType type;
unsigned int key_size;
unsigned int value_size;
unsigned int inner_map_fd;
}; };
struct ptype_descr { enum class MapType : unsigned int
int size{}; {
int data = -1; UNSPEC,
int end = -1; HASH,
int meta = -1; // data to meta is like end to data. i.e. meta <= data <= end ARRAY
}; };
struct program_info { struct map_def
BpfProgType program_type; {
std::vector<map_def> map_defs; int original_fd;
ptype_descr descriptor; 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; extern program_info global_program_info;
struct raw_program { struct raw_program
std::string filename; {
std::string section; std::string filename;
std::vector<char> prog; std::string section;
program_info info; std::vector<char> prog;
program_info info;
}; };
constexpr int xdp_regions = 5 * 4; constexpr int xdp_regions = 5 * 4;

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

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

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

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

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

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

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

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

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

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