Skip to content

Commit

Permalink
feat: add events dimensions file generator in modern probe
Browse files Browse the repository at this point in the history
Signed-off-by: Leonardo Di Giovanna <[email protected]>
  • Loading branch information
ekoops committed Jan 20, 2025
1 parent d327a3b commit 95c1ee8
Show file tree
Hide file tree
Showing 15 changed files with 300 additions and 305 deletions.
1 change: 1 addition & 0 deletions CLANG_FORMAT_VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
18.1.8
1 change: 1 addition & 0 deletions CMAKE_FORMAT_VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.6.13
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@
# mofidy the following variables to match your paths
CLANG_FORMAT_EXE ?= clang-format
CLANG_FORMAT_VERSION = "$(shell ${CLANG_FORMAT_EXE} --version | grep -o '[0-9]*\.[0-9]*\.[0-9]*')"
CLANG_FORMAT_DESIRED_VERSION ="18.1.8"
CLANG_FORMAT_DESIRED_VERSION ?= $(shell cat CLANG_FORMAT_VERSION)

CMAKE_FORMAT_EXE ?= cmake-format
CMAKE_FORMAT_VERSION = "$(shell ${CMAKE_FORMAT_EXE} --version | grep -o '[0-9]*\.[0-9]*\.[0-9]*')"
CMAKE_FORMAT_DESIRED_VERSION = "0.6.13"
CMAKE_FORMAT_DESIRED_VERSION ?= $(shell cat CMAKE_FORMAT_VERSION)

PROJECT_ROOT_DIR = $(shell git rev-parse --show-toplevel)

Expand Down
30 changes: 29 additions & 1 deletion driver/modern_bpf/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,8 @@ list(
${LIBBPF_INTERFACE_INCLUDE}
${MODERN_PROBE_INCLUDE}
-I${PPM_INCLUDE}
-I${MODERN_BPF_EVENTS_DIMENSIONS_FILE_DIR}
-I${CMAKE_CURRENT_SOURCE_DIR}/definitions
-isystem
)

Expand All @@ -256,6 +258,32 @@ file(GLOB_RECURSE BPF_H_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h)
# Search all bpf.c files
file(GLOB_RECURSE BPF_C_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.bpf.c)

# ##################################################################################################
# Generate the events dimensions file generator executable.
# ##################################################################################################

add_executable(
events_dimensions_generator ${CMAKE_CURRENT_SOURCE_DIR}/definitions/generator/generator.cpp
)
target_link_libraries(events_dimensions_generator PRIVATE scap_event_schema)
add_dependencies(events_dimensions_generator scap_event_schema)

# ##################################################################################################
# Generate the events dimensions file.
# ##################################################################################################

set(BPF_EVENTS_DIMENSIONS_FILE ${MODERN_BPF_EVENTS_DIMENSIONS_FILE_DIR}/events_dimensions.h)
add_custom_command(
OUTPUT ${BPF_EVENTS_DIMENSIONS_FILE}
COMMAND events_dimensions_generator ${BPF_EVENTS_DIMENSIONS_FILE}
VERBATIM
DEPENDS events_dimensions_generator ${CMAKE_CURRENT_SOURCE_DIR}/../event_table.c
COMMENT
"${MODERN_BPF_LOG_PREFIX} Building events dimensions file: ${BPF_EVENTS_DIMENSIONS_FILE}"
)

add_custom_target(EventsDimensions ALL DEPENDS ${BPF_EVENTS_DIMENSIONS_FILE})

# ##################################################################################################
# Generate an `bpf.o` file for every `bpf.c`
# ##################################################################################################
Expand All @@ -278,7 +306,7 @@ foreach(BPF_C_FILE ${BPF_C_FILES})
${BPF_O_FILE}
VERBATIM
DEPENDS lbpf
DEPENDS ${BPF_C_FILE} ${BPF_H_FILES}
DEPENDS ${BPF_C_FILE} ${BPF_H_FILES} EventsDimensions
COMMENT "${MODERN_BPF_LOG_PREFIX} Building BPF object: ${BPF_O_FILE}"
)

Expand Down
285 changes: 0 additions & 285 deletions driver/modern_bpf/definitions/events_dimensions.h

This file was deleted.

233 changes: 233 additions & 0 deletions driver/modern_bpf/definitions/generator/generator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
#include <functional>
#include <iostream>
#include <map>
#include <sstream>
#include <fstream>

#include "driver/ppm_events_public.h"

extern const struct ppm_event_info g_event_info[];

auto PREFACE = R"(// SPDX-License-Identifier: GPL-2.0-only OR MIT
/*
* Copyright (C) 2025 The Falco Authors.
*
* This file is dual licensed under either the MIT or GPL 2. See MIT.txt
* or GPL2.txt for full copies of the license.
*/
#ifndef __EVENT_DIMENSIONS_H__
#define __EVENT_DIMENSIONS_H__
#include "vmlinux.h"
/* Here we have all the dimensions for fixed-size events.
*/
#define PARAM_LEN 2
#define HEADER_LEN sizeof(struct ppm_evt_hdr)
/// TODO: We have to move these in the event_table.c. Right now we don't
/// want to touch scap tables.
/* Syscall events */
)";

auto POSTFACE = R"(
#endif /* __EVENT_DIMENSIONS_H__ */
)";

// Use the following macro to get the stringified version of the C expression retrieving the type
// size (e.g.: SIZE_OF_EXPR(uint8_t) is resolved in "sizeof(uint8_t)").
#define SIZE_OF_EXPR(type) SIZE_OF_EXPR_##type

// Generate the "sizeof" stringified expression for the listed types. New handled types must be
// appended to the list.
#define SIZE_OF_EXPR_DECL_LIST_GEN(FN) \
FN(int8_t) \
FN(int16_t) \
FN(int32_t) \
FN(int64_t) \
FN(uint8_t) \
FN(uint16_t) \
FN(uint32_t) \
FN(uint64_t)
#define SIZE_OF_EXPR_DECL(type) char SIZE_OF_EXPR(type)[] = "sizeof(" #type ")";
SIZE_OF_EXPR_DECL_LIST_GEN(SIZE_OF_EXPR_DECL)
#undef SIZE_OF_EXPR_DECL
#undef SIZE_OF_EXPR_DECL_LIST_GEN

// Special expressions denoting variable size or unused parameter types.
char SIZE_OF_EXPR_VARIABLE_SIZE[] = "<variable_size>", SIZE_OF_EXPR_UNUSED[] = "<unused>";

// Table containing the mapping between parameter types and the corresponding stringified "sizeof"
// expression.
std::map<long long, char *> type_to_size_expr{
{PT_NONE, SIZE_OF_EXPR_UNUSED},
{PT_INT8, SIZE_OF_EXPR(int8_t)},
{PT_INT16, SIZE_OF_EXPR(int16_t)},
{PT_INT32, SIZE_OF_EXPR(int32_t)},
{PT_INT64, SIZE_OF_EXPR(int64_t)},
{PT_UINT8, SIZE_OF_EXPR(uint8_t)},
{PT_UINT16, SIZE_OF_EXPR(uint16_t)},
{PT_UINT32, SIZE_OF_EXPR(uint32_t)},
{PT_UINT64, SIZE_OF_EXPR(uint64_t)},
{PT_CHARBUF, SIZE_OF_EXPR_VARIABLE_SIZE},
{PT_BYTEBUF, SIZE_OF_EXPR_VARIABLE_SIZE},
{PT_ERRNO, SIZE_OF_EXPR(int64_t)},
{PT_SOCKADDR, SIZE_OF_EXPR_VARIABLE_SIZE},
{PT_SOCKTUPLE, SIZE_OF_EXPR_VARIABLE_SIZE},
{PT_FD, SIZE_OF_EXPR(int64_t)},
{PT_PID, SIZE_OF_EXPR(int64_t)},
{PT_FDLIST, SIZE_OF_EXPR_VARIABLE_SIZE},
{PT_FSPATH, SIZE_OF_EXPR_VARIABLE_SIZE},
{PT_SYSCALLID, SIZE_OF_EXPR(uint16_t)},
{PT_SIGTYPE, SIZE_OF_EXPR(uint8_t)},
{PT_RELTIME, SIZE_OF_EXPR(uint64_t)},
{PT_ABSTIME, SIZE_OF_EXPR(uint64_t)},
{PT_PORT, SIZE_OF_EXPR_UNUSED},
{PT_L4PROTO, SIZE_OF_EXPR_UNUSED},
{PT_SOCKFAMILY, SIZE_OF_EXPR_UNUSED},
{PT_BOOL, SIZE_OF_EXPR_UNUSED},
{PT_IPV4ADDR, SIZE_OF_EXPR_UNUSED},
{PT_DYN, SIZE_OF_EXPR_VARIABLE_SIZE},
{PT_FLAGS8, SIZE_OF_EXPR(uint8_t)},
{PT_FLAGS16, SIZE_OF_EXPR(uint16_t)},
{PT_FLAGS32, SIZE_OF_EXPR(uint32_t)},
{PT_UID, SIZE_OF_EXPR(uint32_t)},
{PT_GID, SIZE_OF_EXPR(uint32_t)},
{PT_DOUBLE, SIZE_OF_EXPR_UNUSED},
{PT_SIGSET, SIZE_OF_EXPR(uint32_t)},
{PT_CHARBUFARRAY, SIZE_OF_EXPR_VARIABLE_SIZE},
{PT_CHARBUF_PAIR_ARRAY, SIZE_OF_EXPR_VARIABLE_SIZE},
{PT_IPV4NET, SIZE_OF_EXPR_UNUSED},
{PT_IPV6ADDR, SIZE_OF_EXPR_UNUSED},
{PT_IPV6NET, SIZE_OF_EXPR_UNUSED},
{PT_IPADDR, SIZE_OF_EXPR_UNUSED},
{PT_IPNET, SIZE_OF_EXPR_UNUSED},
{PT_MODE, SIZE_OF_EXPR(uint32_t)},
{PT_FSRELPATH, SIZE_OF_EXPR_VARIABLE_SIZE},
{PT_ENUMFLAGS8, SIZE_OF_EXPR(uint8_t)},
{PT_ENUMFLAGS16, SIZE_OF_EXPR(uint16_t)},
{PT_ENUMFLAGS32, SIZE_OF_EXPR(uint32_t)},
};

// is_fixed_size_event determines if the provided event has a fixed size or not.
bool is_fixed_size_event(struct ppm_event_info const *const evt) {
for(int j = 0; j < evt->nparams; j++) {
auto &param = evt->params[j];
auto const param_type = param.type;

auto it = type_to_size_expr.find(param_type);
if(it == type_to_size_expr.end()) {
throw std::runtime_error("Unknown event parameter type: " + std::to_string(param_type));
}

auto const size_expr = it->second;
// Just compare pointers is enough.
if(size_expr == SIZE_OF_EXPR_UNUSED) {
throw std::runtime_error("Unexpected unused event parameter type: " +
std::to_string(param_type));
}
if(size_expr == SIZE_OF_EXPR_VARIABLE_SIZE) {
return false;
}
}
return true;
}

// get_vent_size_expr_counts returns, given the provided event and the resulting size expression of
// its parameters, a map containing, for each size expression, the number of occurrences.
std::map<std::string, size_t> get_event_size_expr_counts(struct ppm_event_info const *const evt) {
std::map<std::string, size_t> size_expr_counts;
for(int i = 0; i < evt->nparams; i++) {
auto const &param = evt->params[i];
auto const param_type = param.type;
auto const it = type_to_size_expr.find(param_type);
if(it == type_to_size_expr.end()) {
throw std::runtime_error("Unknown event parameter type: " + std::to_string(param_type));
}
auto const size_expr = it->second;
size_expr_counts[size_expr]++;
}
return size_expr_counts;
}

// output_event_size outputs the event size macro for the provided event into the provided output
// stream.
void output_event_size(std::ostream &os,
struct ppm_event_info const *const evt,
bool const is_enter_evt) {
// Exclude old versions.
if(evt->flags & EF_OLD_VERSION) {
return;
}

std::string name{evt->name};
// Ignore events without name.
if(name == "NA") {
return;
}

// Exclude events not having a fixed size.
if(!is_fixed_size_event(evt)) {
return;
}

// Generate the complete event size macro name.
std::transform(name.cbegin(), name.cend(), name.begin(), toupper);
if((evt->category & EC_TRACEPOINT) == 0) {
name += is_enter_evt ? "_E" : "_X";
}
name += "_SIZE";

// The event contains at least the header.
os << "#define " << name << " HEADER_LEN";

auto const params_num = evt->nparams;

// Count the number of occurrences for each size expression.
auto size_expr_counts = get_event_size_expr_counts(evt);

// Output "size expression" * "number of occurrences of size expression", for each size
// expression.
for(auto const &[size_expr, count] : size_expr_counts) {
os << " + " << size_expr;
if(count != 1) {
os << " * " << count;
}
}

// Add "number of parameters" * PARAM_LEN, to account the size of each parameter length.
if(params_num != 0) {
os << " + PARAM_LEN";
if(params_num != 1) {
os << " * " << params_num;
}
}
os << '\n';
}

int main(int argc, char *argv[]) {
if(argc != 2) {
std::cerr << "Usage: " << argv[0] << " <filepath>\n";
std::exit(EXIT_FAILURE);
}

std::string filepath{argv[1]};

// Build file content.
std::ostringstream oss;
oss << PREFACE;
for(int i = 0; i < PPM_EVENT_MAX; i++) {
output_event_size(oss, &g_event_info[i], i % 2 == 0);
}
oss << POSTFACE;

// Write content to file.
std::ofstream f{filepath, std::fstream::out | std::fstream::trunc};
f << oss.str();
f.close();

return 0;
}
2 changes: 1 addition & 1 deletion driver/modern_bpf/helpers/interfaces/fixed_size_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@

#pragma once

#include <definitions/events_dimensions.h>
#include <events_dimensions.h>
#include <helpers/store/ringbuf_store_params.h>
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ int BPF_PROG(t_hotplug) {
* the event collection.
*/
struct ringbuf_struct ringbuf;
ringbuf.reserved_event_size = HOTPLUG_E_SIZE;
ringbuf.reserved_event_size = CPU_HOTPLUG_E_SIZE;
ringbuf.event_type = PPME_CPU_HOTPLUG_E;
ringbuf.data = bpf_ringbuf_reserve(rb, HOTPLUG_E_SIZE, 0);
ringbuf.data = bpf_ringbuf_reserve(rb, CPU_HOTPLUG_E_SIZE, 0);
if(!ringbuf.data) {
counter->n_drops_buffer++;
return 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ int BPF_PROG(sched_switch, bool preempt, struct task_struct *prev, struct task_s
/// TODO: we could avoid switches from kernel threads to kernel threads (?).

struct ringbuf_struct ringbuf;
if(!ringbuf__reserve_space(&ringbuf, SCHED_SWITCH_SIZE, PPME_SCHEDSWITCH_6_E)) {
if(!ringbuf__reserve_space(&ringbuf, SWITCH_SIZE, PPME_SCHEDSWITCH_6_E)) {
return 0;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ int BPF_PROG(signal_deliver, int sig, struct kernel_siginfo *info, struct k_siga
}

struct ringbuf_struct ringbuf;
if(!ringbuf__reserve_space(&ringbuf, SIGNAL_DELIVER_SIZE, PPME_SIGNALDELIVER_E)) {
if(!ringbuf__reserve_space(&ringbuf, SIGNALDELIVER_SIZE, PPME_SIGNALDELIVER_E)) {
return 0;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
SEC("tp_btf/sys_enter")
int BPF_PROG(generic_e, struct pt_regs *regs, long id) {
struct ringbuf_struct ringbuf;
if(!ringbuf__reserve_space(&ringbuf, GENERIC_E_SIZE, PPME_GENERIC_E)) {
if(!ringbuf__reserve_space(&ringbuf, SYSCALL_E_SIZE, PPME_GENERIC_E)) {
return 0;
}

Expand Down Expand Up @@ -52,7 +52,7 @@ int BPF_PROG(generic_e, struct pt_regs *regs, long id) {
SEC("tp_btf/sys_exit")
int BPF_PROG(generic_x, struct pt_regs *regs, long ret) {
struct ringbuf_struct ringbuf;
if(!ringbuf__reserve_space(&ringbuf, GENERIC_X_SIZE, PPME_GENERIC_X)) {
if(!ringbuf__reserve_space(&ringbuf, SYSCALL_X_SIZE, PPME_GENERIC_X)) {
return 0;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
SEC("tp_btf/sys_enter")
int BPF_PROG(pread64_e, struct pt_regs *regs, long id) {
struct ringbuf_struct ringbuf;
if(!ringbuf__reserve_space(&ringbuf, PREAD64_E_SIZE, PPME_SYSCALL_PREAD_E)) {
if(!ringbuf__reserve_space(&ringbuf, PREAD_E_SIZE, PPME_SYSCALL_PREAD_E)) {
return 0;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
SEC("tp_btf/sys_enter")
int BPF_PROG(prlimit64_e, struct pt_regs *regs, long id) {
struct ringbuf_struct ringbuf;
if(!ringbuf__reserve_space(&ringbuf, PRLIMIT64_E_SIZE, PPME_SYSCALL_PRLIMIT_E)) {
if(!ringbuf__reserve_space(&ringbuf, PRLIMIT_E_SIZE, PPME_SYSCALL_PRLIMIT_E)) {
return 0;
}

Expand Down Expand Up @@ -43,7 +43,7 @@ int BPF_PROG(prlimit64_e, struct pt_regs *regs, long id) {
SEC("tp_btf/sys_exit")
int BPF_PROG(prlimit64_x, struct pt_regs *regs, long ret) {
struct ringbuf_struct ringbuf;
if(!ringbuf__reserve_space(&ringbuf, PRLIMIT64_X_SIZE, PPME_SYSCALL_PRLIMIT_X)) {
if(!ringbuf__reserve_space(&ringbuf, PRLIMIT_X_SIZE, PPME_SYSCALL_PRLIMIT_X)) {
return 0;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
SEC("tp_btf/sys_enter")
int BPF_PROG(pwrite64_e, struct pt_regs *regs, long id) {
struct ringbuf_struct ringbuf;
if(!ringbuf__reserve_space(&ringbuf, PWRITE64_E_SIZE, PPME_SYSCALL_PWRITE_E)) {
if(!ringbuf__reserve_space(&ringbuf, PWRITE_E_SIZE, PPME_SYSCALL_PWRITE_E)) {
return 0;
}

Expand Down
Loading

0 comments on commit 95c1ee8

Please sign in to comment.