Skip to content

Commit

Permalink
Consistent format of the eBPF code (#310)
Browse files Browse the repository at this point in the history
Signed-off-by: Florian Lehner <[email protected]>
  • Loading branch information
florianl authored Jan 17, 2025
1 parent cc2b97c commit 12badae
Show file tree
Hide file tree
Showing 27 changed files with 1,619 additions and 1,446 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/unit-test-on-pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ jobs:
CGO_ENABLED: 1
with:
version: ${{ steps.linter-version.outputs.version }}
- name: Lint eBPF code
run: |
sudo apt update
sudo apt install -y clang-format-17
make lint -C support/ebpf
test:
name: Test (${{ matrix.target_arch }})
Expand Down
7 changes: 6 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.PHONY: all all-common clean ebpf generate test test-deps protobuf docker-image agent legal \
integration-test-binaries codespell lint linter-version debug debug-agent ebpf-profiler
integration-test-binaries codespell lint linter-version debug debug-agent ebpf-profiler \
format-ebpf

SHELL := /usr/bin/env bash

Expand Down Expand Up @@ -76,9 +77,13 @@ ebpf-profiler: generate ebpf

GOLANGCI_LINT_VERSION = "v1.60.1"
lint: generate vanity-import-check
$(MAKE) lint -C support/ebpf
go run github.com/golangci/golangci-lint/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION) version
go run github.com/golangci/golangci-lint/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION) run

format-ebpf:
$(MAKE) format -C support/ebpf

linter-version:
@echo $(GOLANGCI_LINT_VERSION)

Expand Down
17 changes: 17 additions & 0 deletions support/ebpf/.clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
BasedOnStyle: LLVM
AlignAfterOpenBracket: AlwaysBreak
AllowShortFunctionsOnASingleLine: Inline
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterFunction: true
SplitEmptyFunction: false
BreakBeforeBraces: Custom
BreakStringLiterals: false
ColumnLimit: 100
ConstructorInitializerAllOnOneLineOrOnePerLine: true
IndentPPDirectives: BeforeHash
AlignConsecutiveMacros: AcrossComments
AlignConsecutiveAssignments: AcrossComments
AllowShortCaseLabelsOnASingleLine: true
ContinuationIndentWidth: 2
7 changes: 7 additions & 0 deletions support/ebpf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ SHELL ?= bash
BPF_CLANG ?= clang-17
BPF_LINK ?= llvm-link-17
LLC ?= llc-17
CLANG_FORMAT ?= clang-format-17

DEBUG_FLAGS = -DOPTI_DEBUG -g

Expand Down Expand Up @@ -86,5 +87,11 @@ baseline: $(TRACER_NAME)
bloatcheck: $(TRACER_NAME)
python3 bloat-o-meter $(TRACER_NAME).baseline $(TRACER_NAME)

lint:
$(CLANG_FORMAT) -Werror --dry-run -style=file *.[ch]

format:
$(CLANG_FORMAT) -i -style=file *.[ch]

clean:
rm -f *.o
241 changes: 119 additions & 122 deletions support/ebpf/bpfdefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,50 +9,57 @@
// dispatch the BPF API to helpers implemented in ebpfhelpers.go.
#define SEC(NAME)

#define printt(fmt, ...) bpf_log(fmt, ##__VA_ARGS__)
#define printt(fmt, ...) bpf_log(fmt, ##__VA_ARGS__)
#define DEBUG_PRINT(fmt, ...) bpf_log(fmt, ##__VA_ARGS__)
#define OPTI_DEBUG

// BPF helpers. Mostly stubs to dispatch the call to Go code with the context ID.
int bpf_tail_call(void *ctx, bpf_map_def *map, int index);
unsigned long long bpf_ktime_get_ns(void);
int bpf_get_current_comm(void *, int);

static inline long bpf_probe_read_user(void *buf, u32 sz, const void *ptr) {
long __bpf_probe_read_user(u64, void *, u32, const void *);
return __bpf_probe_read_user(__cgo_ctx->id, buf, sz, ptr);
}

static inline long bpf_probe_read_kernel(void *buf, u32 sz, const void *ptr) {
return -1;
}

static inline u64 bpf_get_current_pid_tgid(void) {
return __cgo_ctx->id;
}

static inline void *bpf_map_lookup_elem(bpf_map_def *map, const void *key) {
void *__bpf_map_lookup_elem(u64, bpf_map_def *, const void *);
return __bpf_map_lookup_elem(__cgo_ctx->id, map, key);
}

static inline int bpf_map_update_elem(bpf_map_def *map, const void *key, const void *val,
u64 flags) {
return -1;
}

static inline int bpf_map_delete_elem(bpf_map_def *map, const void *key) {
return -1;
}

static inline int bpf_perf_event_output(void *ctx, bpf_map_def *mapdef, unsigned long long flags,
void *data, int size) {
return 0;
}

static inline int bpf_get_stackid(void *ctx, bpf_map_def *map, u64 flags) {
return -1;
}
// BPF helpers. Mostly stubs to dispatch the call to Go code with the context ID.
int bpf_tail_call(void *ctx, bpf_map_def *map, int index);
unsigned long long bpf_ktime_get_ns(void);
int bpf_get_current_comm(void *, int);

static inline long bpf_probe_read_user(void *buf, u32 sz, const void *ptr)
{
long __bpf_probe_read_user(u64, void *, u32, const void *);
return __bpf_probe_read_user(__cgo_ctx->id, buf, sz, ptr);
}

static inline long bpf_probe_read_kernel(void *buf, u32 sz, const void *ptr)
{
return -1;
}

static inline u64 bpf_get_current_pid_tgid(void)
{
return __cgo_ctx->id;
}

static inline void *bpf_map_lookup_elem(bpf_map_def *map, const void *key)
{
void *__bpf_map_lookup_elem(u64, bpf_map_def *, const void *);
return __bpf_map_lookup_elem(__cgo_ctx->id, map, key);
}

static inline int bpf_map_update_elem(bpf_map_def *map, const void *key, const void *val, u64 flags)
{
return -1;
}

static inline int bpf_map_delete_elem(bpf_map_def *map, const void *key)
{
return -1;
}

static inline int bpf_perf_event_output(
void *ctx, bpf_map_def *mapdef, unsigned long long flags, void *data, int size)
{
return 0;
}

static inline int bpf_get_stackid(void *ctx, bpf_map_def *map, u64 flags)
{
return -1;
}

#else // TESTING_COREDUMP

Expand All @@ -61,89 +68,79 @@
// definitions of bpf helper functions we need, as found in
// https://elixir.bootlin.com/linux/v4.11/source/samples/bpf/bpf_helpers.h

static void *(*bpf_map_lookup_elem)(void *map, void *key) =
(void *)BPF_FUNC_map_lookup_elem;
static int (*bpf_map_update_elem)(void *map, void *key, void *value, u64 flags) =
(void *)BPF_FUNC_map_update_elem;
static int (*bpf_map_delete_elem)(void *map, void *key) =
(void *)BPF_FUNC_map_delete_elem;
static int (*bpf_probe_read)(void *dst, int size, const void *unsafe_ptr) =
(void *)BPF_FUNC_probe_read;
static unsigned long long (*bpf_ktime_get_ns)(void) =
(void *)BPF_FUNC_ktime_get_ns;
static unsigned long long (*bpf_get_current_pid_tgid)(void) =
(void *)BPF_FUNC_get_current_pid_tgid;
static int (*bpf_get_current_comm)(void *buf, int buf_size) =
(void *) BPF_FUNC_get_current_comm;
static void (*bpf_tail_call)(void *ctx, void *map, int index) =
(void *)BPF_FUNC_tail_call;
static unsigned long long (*bpf_get_current_task)(void) =
(void *)BPF_FUNC_get_current_task;
static int (*bpf_perf_event_output)(void *ctx, void *map, unsigned long long flags, void *data, int size) =
(void *)BPF_FUNC_perf_event_output;
static int (*bpf_get_stackid)(void *ctx, void *map, u64 flags) =
(void *)BPF_FUNC_get_stackid;
static unsigned long long (*bpf_get_prandom_u32)(void) =
(void *) BPF_FUNC_get_prandom_u32;

__attribute__ ((format (printf, 1, 3)))
static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
(void *)BPF_FUNC_trace_printk;

static long (*bpf_probe_read_user)(void *dst, int size, const void *unsafe_ptr) =
(void *)BPF_FUNC_probe_read_user;
static long (*bpf_probe_read_kernel)(void *dst, int size, const void *unsafe_ptr) =
(void *)BPF_FUNC_probe_read_kernel;

// The sizeof in bpf_trace_printk() must include \0, else no output
// is generated. The \n is not needed on 5.8+ kernels, but definitely on
// 5.4 kernels.
#define printt(fmt, ...) \
({ \
const char ____fmt[] = fmt "\n"; \
bpf_trace_printk(____fmt, sizeof(____fmt), ##__VA_ARGS__); \
})

#ifdef OPTI_DEBUG
#define DEBUG_PRINT(fmt, ...) printt(fmt, ##__VA_ARGS__);

// Sends `SIGTRAP` to the current task, killing it and capturing a coredump.
//
// Only use this in code paths that you expect to be hit by a very specific process that you
// intend to debug. Placing it into frequently taken code paths might otherwise take down
// important system processes like sshd or your window manager. For frequently taken cases,
// prefer using the `DEBUG_CAPTURE_COREDUMP_IF_TGID` macro.
//
// This macro requires linking against kernel headers >= 5.6.
#define DEBUG_CAPTURE_COREDUMP() \
({ \
/* We don't define `bpf_send_signal_thread` globally because it requires a */ \
/* rather recent kernel (>= 5.6) and otherwise breaks builds of older versions. */ \
long (*bpf_send_signal_thread)(u32 sig) = (void *)BPF_FUNC_send_signal_thread; \
bpf_send_signal_thread(SIGTRAP); \
static void *(*bpf_map_lookup_elem)(void *map, void *key) = (void *)BPF_FUNC_map_lookup_elem;
static int (*bpf_map_update_elem)(void *map, void *key, void *value, u64 flags) = (void *)
BPF_FUNC_map_update_elem;
static int (*bpf_map_delete_elem)(void *map, void *key) = (void *)BPF_FUNC_map_delete_elem;
static int (*bpf_probe_read)(void *dst, int size, const void *unsafe_ptr) = (void *)
BPF_FUNC_probe_read;
static unsigned long long (*bpf_ktime_get_ns)(void) = (void *)BPF_FUNC_ktime_get_ns;
static unsigned long long (*bpf_get_current_pid_tgid)(void) = (void *)BPF_FUNC_get_current_pid_tgid;
static int (*bpf_get_current_comm)(void *buf, int buf_size) = (void *)BPF_FUNC_get_current_comm;
static void (*bpf_tail_call)(void *ctx, void *map, int index) = (void *)BPF_FUNC_tail_call;
static unsigned long long (*bpf_get_current_task)(void) = (void *)BPF_FUNC_get_current_task;
static int (*bpf_perf_event_output)(
void *ctx, void *map, unsigned long long flags, void *data, int size) = (void *)
BPF_FUNC_perf_event_output;
static int (*bpf_get_stackid)(void *ctx, void *map, u64 flags) = (void *)BPF_FUNC_get_stackid;
static unsigned long long (*bpf_get_prandom_u32)(void) = (void *)BPF_FUNC_get_prandom_u32;

__attribute__((format(printf, 1, 3))) static int (*bpf_trace_printk)(
const char *fmt, int fmt_size, ...) = (void *)BPF_FUNC_trace_printk;

static long (*bpf_probe_read_user)(void *dst, int size, const void *unsafe_ptr) = (void *)
BPF_FUNC_probe_read_user;
static long (*bpf_probe_read_kernel)(void *dst, int size, const void *unsafe_ptr) = (void *)
BPF_FUNC_probe_read_kernel;

// The sizeof in bpf_trace_printk() must include \0, else no output
// is generated. The \n is not needed on 5.8+ kernels, but definitely on
// 5.4 kernels.
#define printt(fmt, ...) \
({ \
const char ____fmt[] = fmt "\n"; \
bpf_trace_printk(____fmt, sizeof(____fmt), ##__VA_ARGS__); \
})

// Like `DEBUG_CAPTURE_COREDUMP`, but only coredumps if the current task is a member of the given
// thread group ID ("process").
#define DEBUG_CAPTURE_COREDUMP_IF_TGID(tgid) \
({ \
if (bpf_get_current_pid_tgid() >> 32 == (tgid)) { \
DEBUG_PRINT("coredumping process %d", (tgid)); \
DEBUG_CAPTURE_COREDUMP(); \
} \
})
#else
#define DEBUG_PRINT(fmt, ...)
#define DEBUG_CAPTURE_COREDUMP()
#define DEBUG_CAPTURE_COREDUMP_IF_TGID(tgid)
#endif

// Definition of SEC as used by the Linux kernel in tools/lib/bpf/bpf_helpers.h for clang compilations.
#define SEC(name) \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wignored-attributes\"") \
__attribute__((section(name), used)) \
_Pragma("GCC diagnostic pop")
#ifdef OPTI_DEBUG
#define DEBUG_PRINT(fmt, ...) printt(fmt, ##__VA_ARGS__);

// Sends `SIGTRAP` to the current task, killing it and capturing a coredump.
//
// Only use this in code paths that you expect to be hit by a very specific process that you
// intend to debug. Placing it into frequently taken code paths might otherwise take down
// important system processes like sshd or your window manager. For frequently taken cases,
// prefer using the `DEBUG_CAPTURE_COREDUMP_IF_TGID` macro.
//
// This macro requires linking against kernel headers >= 5.6.
#define DEBUG_CAPTURE_COREDUMP() \
({ \
/* We don't define `bpf_send_signal_thread` globally because it requires a */ \
/* rather recent kernel (>= 5.6) and otherwise breaks builds of older versions. */ \
long (*bpf_send_signal_thread)(u32 sig) = (void *)BPF_FUNC_send_signal_thread; \
bpf_send_signal_thread(SIGTRAP); \
})

// Like `DEBUG_CAPTURE_COREDUMP`, but only coredumps if the current task is a member of the
// given thread group ID ("process").
#define DEBUG_CAPTURE_COREDUMP_IF_TGID(tgid) \
({ \
if (bpf_get_current_pid_tgid() >> 32 == (tgid)) { \
DEBUG_PRINT("coredumping process %d", (tgid)); \
DEBUG_CAPTURE_COREDUMP(); \
} \
})
#else
#define DEBUG_PRINT(fmt, ...)
#define DEBUG_CAPTURE_COREDUMP()
#define DEBUG_CAPTURE_COREDUMP_IF_TGID(tgid)
#endif

// Definition of SEC as used by the Linux kernel in tools/lib/bpf/bpf_helpers.h for clang
// compilations.
#define SEC(name) \
_Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wignored-attributes\"") \
__attribute__((section(name), used)) _Pragma("GCC diagnostic pop")

#endif // !TESTING_COREDUMP

Expand Down
Loading

0 comments on commit 12badae

Please sign in to comment.