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:
Родитель
a8045d4f3e
Коммит
00bd6ef2da
|
@ -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 §ion) {
|
||||
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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче