mirror of
https://github.com/h3xduck/TripleCross.git
synced 2025-12-20 16:53:07 +08:00
Setup development environment with libbpf
This commit is contained in:
6
external/libbpf-bootstrap/examples/c/.gitignore
vendored
Normal file
6
external/libbpf-bootstrap/examples/c/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
/.output
|
||||
/bootstrap
|
||||
/minimal
|
||||
/uprobe
|
||||
/kprobe
|
||||
/fentry
|
||||
47
external/libbpf-bootstrap/examples/c/CMakeLists.txt
vendored
Normal file
47
external/libbpf-bootstrap/examples/c/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(examples)
|
||||
|
||||
# Tell cmake where to find BpfObject module
|
||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../tools/cmake)
|
||||
|
||||
# Build vendored libbpf
|
||||
include(ExternalProject)
|
||||
ExternalProject_Add(libbpf
|
||||
PREFIX libbpf
|
||||
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../libbpf/src
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND make
|
||||
BUILD_STATIC_ONLY=1
|
||||
OBJDIR=${CMAKE_CURRENT_BINARY_DIR}/libbpf/libbpf
|
||||
DESTDIR=${CMAKE_CURRENT_BINARY_DIR}/libbpf
|
||||
INCLUDEDIR=
|
||||
LIBDIR=
|
||||
UAPIDIR=
|
||||
install
|
||||
BUILD_IN_SOURCE TRUE
|
||||
INSTALL_COMMAND ""
|
||||
STEP_TARGETS build
|
||||
)
|
||||
|
||||
# Set BpfObject input parameters -- note this is usually not necessary unless
|
||||
# you're in a highly vendored environment (like libbpf-bootstrap)
|
||||
set(BPFOBJECT_BPFTOOL_EXE ${CMAKE_CURRENT_SOURCE_DIR}/../../tools/bpftool)
|
||||
set(BPFOBJECT_VMLINUX_H ${CMAKE_CURRENT_SOURCE_DIR}/../../vmlinux/vmlinux.h)
|
||||
set(LIBBPF_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}/libbpf)
|
||||
set(LIBBPF_LIBRARIES ${CMAKE_CURRENT_BINARY_DIR}/libbpf/libbpf.a)
|
||||
find_package(BpfObject REQUIRED)
|
||||
|
||||
# Create an executable for each application
|
||||
file(GLOB apps *.bpf.c)
|
||||
foreach(app ${apps})
|
||||
get_filename_component(app_stem ${app} NAME_WE)
|
||||
|
||||
# Build object skeleton and depend skeleton on libbpf build
|
||||
bpf_object(${app_stem} ${app_stem}.bpf.c)
|
||||
add_dependencies(${app_stem}_skel libbpf-build)
|
||||
|
||||
add_executable(${app_stem} ${app_stem}.c)
|
||||
target_link_libraries(${app_stem} ${app_stem}_skel)
|
||||
endforeach()
|
||||
89
external/libbpf-bootstrap/examples/c/Makefile
vendored
Normal file
89
external/libbpf-bootstrap/examples/c/Makefile
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
|
||||
OUTPUT := .output
|
||||
CLANG ?= clang
|
||||
LLVM_STRIP ?= llvm-strip
|
||||
BPFTOOL ?= $(abspath ../../tools/bpftool)
|
||||
LIBBPF_SRC := $(abspath ../../libbpf/src)
|
||||
LIBBPF_OBJ := $(abspath $(OUTPUT)/libbpf.a)
|
||||
VMLINUX := ../../vmlinux/vmlinux.h
|
||||
# Use our own libbpf API headers and Linux UAPI headers distributed with
|
||||
# libbpf to avoid dependency on system-wide headers, which could be missing or
|
||||
# outdated
|
||||
INCLUDES := -I$(OUTPUT) -I../../libbpf/include/uapi -I$(dir $(VMLINUX))
|
||||
CFLAGS := -g -Wall
|
||||
ARCH := $(shell uname -m | sed 's/x86_64/x86/')
|
||||
|
||||
APPS = minimal bootstrap uprobe kprobe fentry
|
||||
|
||||
# Get Clang's default includes on this system. We'll explicitly add these dirs
|
||||
# to the includes list when compiling with `-target bpf` because otherwise some
|
||||
# architecture-specific dirs will be "missing" on some architectures/distros -
|
||||
# headers such as asm/types.h, asm/byteorder.h, asm/socket.h, asm/sockios.h,
|
||||
# sys/cdefs.h etc. might be missing.
|
||||
#
|
||||
# Use '-idirafter': Don't interfere with include mechanics except where the
|
||||
# build would have failed anyways.
|
||||
CLANG_BPF_SYS_INCLUDES = $(shell $(CLANG) -v -E - </dev/null 2>&1 \
|
||||
| sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }')
|
||||
|
||||
ifeq ($(V),1)
|
||||
Q =
|
||||
msg =
|
||||
else
|
||||
Q = @
|
||||
msg = @printf ' %-8s %s%s\n' \
|
||||
"$(1)" \
|
||||
"$(patsubst $(abspath $(OUTPUT))/%,%,$(2))" \
|
||||
"$(if $(3), $(3))";
|
||||
MAKEFLAGS += --no-print-directory
|
||||
endif
|
||||
|
||||
.PHONY: all
|
||||
all: $(APPS)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(call msg,CLEAN)
|
||||
$(Q)rm -rf $(OUTPUT) $(APPS)
|
||||
|
||||
$(OUTPUT) $(OUTPUT)/libbpf:
|
||||
$(call msg,MKDIR,$@)
|
||||
$(Q)mkdir -p $@
|
||||
|
||||
# Build libbpf
|
||||
$(LIBBPF_OBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(OUTPUT)/libbpf
|
||||
$(call msg,LIB,$@)
|
||||
$(Q)$(MAKE) -C $(LIBBPF_SRC) BUILD_STATIC_ONLY=1 \
|
||||
OBJDIR=$(dir $@)/libbpf DESTDIR=$(dir $@) \
|
||||
INCLUDEDIR= LIBDIR= UAPIDIR= \
|
||||
install
|
||||
|
||||
# Build BPF code
|
||||
$(OUTPUT)/%.bpf.o: %.bpf.c $(LIBBPF_OBJ) $(wildcard %.h) $(VMLINUX) | $(OUTPUT)
|
||||
$(call msg,BPF,$@)
|
||||
$(Q)$(CLANG) -g -O2 -target bpf -D__TARGET_ARCH_$(ARCH) $(INCLUDES) $(CLANG_BPF_SYS_INCLUDES) -c $(filter %.c,$^) -o $@
|
||||
$(Q)$(LLVM_STRIP) -g $@ # strip useless DWARF info
|
||||
|
||||
# Generate BPF skeletons
|
||||
$(OUTPUT)/%.skel.h: $(OUTPUT)/%.bpf.o | $(OUTPUT)
|
||||
$(call msg,GEN-SKEL,$@)
|
||||
$(Q)$(BPFTOOL) gen skeleton $< > $@
|
||||
|
||||
# Build user-space code
|
||||
$(patsubst %,$(OUTPUT)/%.o,$(APPS)): %.o: %.skel.h
|
||||
|
||||
$(OUTPUT)/%.o: %.c $(wildcard %.h) | $(OUTPUT)
|
||||
$(call msg,CC,$@)
|
||||
$(Q)$(CC) $(CFLAGS) $(INCLUDES) -c $(filter %.c,$^) -o $@
|
||||
|
||||
# Build application binary
|
||||
$(APPS): %: $(OUTPUT)/%.o $(LIBBPF_OBJ) | $(OUTPUT)
|
||||
$(call msg,BINARY,$@)
|
||||
$(Q)$(CC) $(CFLAGS) $^ -lelf -lz -o $@
|
||||
|
||||
# delete failed targets
|
||||
.DELETE_ON_ERROR:
|
||||
|
||||
# keep intermediate (.skel.h, .bpf.o, etc) targets
|
||||
.SECONDARY:
|
||||
|
||||
112
external/libbpf-bootstrap/examples/c/bootstrap.bpf.c
vendored
Normal file
112
external/libbpf-bootstrap/examples/c/bootstrap.bpf.c
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/* Copyright (c) 2020 Facebook */
|
||||
#include "vmlinux.h"
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_tracing.h>
|
||||
#include <bpf/bpf_core_read.h>
|
||||
#include "bootstrap.h"
|
||||
|
||||
char LICENSE[] SEC("license") = "Dual BSD/GPL";
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_HASH);
|
||||
__uint(max_entries, 8192);
|
||||
__type(key, pid_t);
|
||||
__type(value, u64);
|
||||
} exec_start SEC(".maps");
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_RINGBUF);
|
||||
__uint(max_entries, 256 * 1024);
|
||||
} rb SEC(".maps");
|
||||
|
||||
const volatile unsigned long long min_duration_ns = 0;
|
||||
|
||||
SEC("tp/sched/sched_process_exec")
|
||||
int handle_exec(struct trace_event_raw_sched_process_exec *ctx)
|
||||
{
|
||||
struct task_struct *task;
|
||||
unsigned fname_off;
|
||||
struct event *e;
|
||||
pid_t pid;
|
||||
u64 ts;
|
||||
|
||||
/* remember time exec() was executed for this PID */
|
||||
pid = bpf_get_current_pid_tgid() >> 32;
|
||||
ts = bpf_ktime_get_ns();
|
||||
bpf_map_update_elem(&exec_start, &pid, &ts, BPF_ANY);
|
||||
|
||||
/* don't emit exec events when minimum duration is specified */
|
||||
if (min_duration_ns)
|
||||
return 0;
|
||||
|
||||
/* reserve sample from BPF ringbuf */
|
||||
e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0);
|
||||
if (!e)
|
||||
return 0;
|
||||
|
||||
/* fill out the sample with data */
|
||||
task = (struct task_struct *)bpf_get_current_task();
|
||||
|
||||
e->exit_event = false;
|
||||
e->pid = pid;
|
||||
e->ppid = BPF_CORE_READ(task, real_parent, tgid);
|
||||
bpf_get_current_comm(&e->comm, sizeof(e->comm));
|
||||
|
||||
fname_off = ctx->__data_loc_filename & 0xFFFF;
|
||||
bpf_probe_read_str(&e->filename, sizeof(e->filename), (void *)ctx + fname_off);
|
||||
|
||||
/* successfully submit it to user-space for post-processing */
|
||||
bpf_ringbuf_submit(e, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("tp/sched/sched_process_exit")
|
||||
int handle_exit(struct trace_event_raw_sched_process_template* ctx)
|
||||
{
|
||||
struct task_struct *task;
|
||||
struct event *e;
|
||||
pid_t pid, tid;
|
||||
u64 id, ts, *start_ts, duration_ns = 0;
|
||||
|
||||
/* get PID and TID of exiting thread/process */
|
||||
id = bpf_get_current_pid_tgid();
|
||||
pid = id >> 32;
|
||||
tid = (u32)id;
|
||||
|
||||
/* ignore thread exits */
|
||||
if (pid != tid)
|
||||
return 0;
|
||||
|
||||
/* if we recorded start of the process, calculate lifetime duration */
|
||||
start_ts = bpf_map_lookup_elem(&exec_start, &pid);
|
||||
if (start_ts)
|
||||
duration_ns = bpf_ktime_get_ns() - *start_ts;
|
||||
else if (min_duration_ns)
|
||||
return 0;
|
||||
bpf_map_delete_elem(&exec_start, &pid);
|
||||
|
||||
/* if process didn't live long enough, return early */
|
||||
if (min_duration_ns && duration_ns < min_duration_ns)
|
||||
return 0;
|
||||
|
||||
/* reserve sample from BPF ringbuf */
|
||||
e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0);
|
||||
if (!e)
|
||||
return 0;
|
||||
|
||||
/* fill out the sample with data */
|
||||
task = (struct task_struct *)bpf_get_current_task();
|
||||
|
||||
e->exit_event = true;
|
||||
e->duration_ns = duration_ns;
|
||||
e->pid = pid;
|
||||
e->ppid = BPF_CORE_READ(task, real_parent, tgid);
|
||||
e->exit_code = (BPF_CORE_READ(task, exit_code) >> 8) & 0xff;
|
||||
bpf_get_current_comm(&e->comm, sizeof(e->comm));
|
||||
|
||||
/* send data to user-space for post-processing */
|
||||
bpf_ringbuf_submit(e, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
189
external/libbpf-bootstrap/examples/c/bootstrap.c
vendored
Normal file
189
external/libbpf-bootstrap/examples/c/bootstrap.c
vendored
Normal file
@@ -0,0 +1,189 @@
|
||||
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
|
||||
/* Copyright (c) 2020 Facebook */
|
||||
#include <argp.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <bpf/libbpf.h>
|
||||
#include "bootstrap.h"
|
||||
#include "bootstrap.skel.h"
|
||||
|
||||
static struct env {
|
||||
bool verbose;
|
||||
long min_duration_ms;
|
||||
} env;
|
||||
|
||||
const char *argp_program_version = "bootstrap 0.0";
|
||||
const char *argp_program_bug_address = "<bpf@vger.kernel.org>";
|
||||
const char argp_program_doc[] =
|
||||
"BPF bootstrap demo application.\n"
|
||||
"\n"
|
||||
"It traces process start and exits and shows associated \n"
|
||||
"information (filename, process duration, PID and PPID, etc).\n"
|
||||
"\n"
|
||||
"USAGE: ./bootstrap [-d <min-duration-ms>] [-v]\n";
|
||||
|
||||
static const struct argp_option opts[] = {
|
||||
{ "verbose", 'v', NULL, 0, "Verbose debug output" },
|
||||
{ "duration", 'd', "DURATION-MS", 0, "Minimum process duration (ms) to report" },
|
||||
{},
|
||||
};
|
||||
|
||||
static error_t parse_arg(int key, char *arg, struct argp_state *state)
|
||||
{
|
||||
switch (key) {
|
||||
case 'v':
|
||||
env.verbose = true;
|
||||
break;
|
||||
case 'd':
|
||||
errno = 0;
|
||||
env.min_duration_ms = strtol(arg, NULL, 10);
|
||||
if (errno || env.min_duration_ms <= 0) {
|
||||
fprintf(stderr, "Invalid duration: %s\n", arg);
|
||||
argp_usage(state);
|
||||
}
|
||||
break;
|
||||
case ARGP_KEY_ARG:
|
||||
argp_usage(state);
|
||||
break;
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct argp argp = {
|
||||
.options = opts,
|
||||
.parser = parse_arg,
|
||||
.doc = argp_program_doc,
|
||||
};
|
||||
|
||||
static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
|
||||
{
|
||||
if (level == LIBBPF_DEBUG && !env.verbose)
|
||||
return 0;
|
||||
return vfprintf(stderr, format, args);
|
||||
}
|
||||
|
||||
static void bump_memlock_rlimit(void)
|
||||
{
|
||||
struct rlimit rlim_new = {
|
||||
.rlim_cur = RLIM_INFINITY,
|
||||
.rlim_max = RLIM_INFINITY,
|
||||
};
|
||||
|
||||
if (setrlimit(RLIMIT_MEMLOCK, &rlim_new)) {
|
||||
fprintf(stderr, "Failed to increase RLIMIT_MEMLOCK limit!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static volatile bool exiting = false;
|
||||
|
||||
static void sig_handler(int sig)
|
||||
{
|
||||
exiting = true;
|
||||
}
|
||||
|
||||
static int handle_event(void *ctx, void *data, size_t data_sz)
|
||||
{
|
||||
const struct event *e = data;
|
||||
struct tm *tm;
|
||||
char ts[32];
|
||||
time_t t;
|
||||
|
||||
time(&t);
|
||||
tm = localtime(&t);
|
||||
strftime(ts, sizeof(ts), "%H:%M:%S", tm);
|
||||
|
||||
if (e->exit_event) {
|
||||
printf("%-8s %-5s %-16s %-7d %-7d [%u]",
|
||||
ts, "EXIT", e->comm, e->pid, e->ppid, e->exit_code);
|
||||
if (e->duration_ns)
|
||||
printf(" (%llums)", e->duration_ns / 1000000);
|
||||
printf("\n");
|
||||
} else {
|
||||
printf("%-8s %-5s %-16s %-7d %-7d %s\n",
|
||||
ts, "EXEC", e->comm, e->pid, e->ppid, e->filename);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct ring_buffer *rb = NULL;
|
||||
struct bootstrap_bpf *skel;
|
||||
int err;
|
||||
|
||||
/* Parse command line arguments */
|
||||
err = argp_parse(&argp, argc, argv, 0, NULL, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Set up libbpf errors and debug info callback */
|
||||
libbpf_set_print(libbpf_print_fn);
|
||||
|
||||
/* Bump RLIMIT_MEMLOCK to create BPF maps */
|
||||
bump_memlock_rlimit();
|
||||
|
||||
/* Cleaner handling of Ctrl-C */
|
||||
signal(SIGINT, sig_handler);
|
||||
signal(SIGTERM, sig_handler);
|
||||
|
||||
/* Load and verify BPF application */
|
||||
skel = bootstrap_bpf__open();
|
||||
if (!skel) {
|
||||
fprintf(stderr, "Failed to open and load BPF skeleton\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Parameterize BPF code with minimum duration parameter */
|
||||
skel->rodata->min_duration_ns = env.min_duration_ms * 1000000ULL;
|
||||
|
||||
/* Load & verify BPF programs */
|
||||
err = bootstrap_bpf__load(skel);
|
||||
if (err) {
|
||||
fprintf(stderr, "Failed to load and verify BPF skeleton\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Attach tracepoints */
|
||||
err = bootstrap_bpf__attach(skel);
|
||||
if (err) {
|
||||
fprintf(stderr, "Failed to attach BPF skeleton\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Set up ring buffer polling */
|
||||
rb = ring_buffer__new(bpf_map__fd(skel->maps.rb), handle_event, NULL, NULL);
|
||||
if (!rb) {
|
||||
err = -1;
|
||||
fprintf(stderr, "Failed to create ring buffer\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Process events */
|
||||
printf("%-8s %-5s %-16s %-7s %-7s %s\n",
|
||||
"TIME", "EVENT", "COMM", "PID", "PPID", "FILENAME/EXIT CODE");
|
||||
while (!exiting) {
|
||||
err = ring_buffer__poll(rb, 100 /* timeout, ms */);
|
||||
/* Ctrl-C will cause -EINTR */
|
||||
if (err == -EINTR) {
|
||||
err = 0;
|
||||
break;
|
||||
}
|
||||
if (err < 0) {
|
||||
printf("Error polling perf buffer: %d\n", err);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
/* Clean up */
|
||||
ring_buffer__free(rb);
|
||||
bootstrap_bpf__destroy(skel);
|
||||
|
||||
return err < 0 ? -err : 0;
|
||||
}
|
||||
19
external/libbpf-bootstrap/examples/c/bootstrap.h
vendored
Normal file
19
external/libbpf-bootstrap/examples/c/bootstrap.h
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
/* Copyright (c) 2020 Facebook */
|
||||
#ifndef __BOOTSTRAP_H
|
||||
#define __BOOTSTRAP_H
|
||||
|
||||
#define TASK_COMM_LEN 16
|
||||
#define MAX_FILENAME_LEN 127
|
||||
|
||||
struct event {
|
||||
int pid;
|
||||
int ppid;
|
||||
unsigned exit_code;
|
||||
unsigned long long duration_ns;
|
||||
char comm[TASK_COMM_LEN];
|
||||
char filename[MAX_FILENAME_LEN];
|
||||
bool exit_event;
|
||||
};
|
||||
|
||||
#endif /* __BOOTSTRAP_H */
|
||||
27
external/libbpf-bootstrap/examples/c/fentry.bpf.c
vendored
Normal file
27
external/libbpf-bootstrap/examples/c/fentry.bpf.c
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/* Copyright (c) 2021 Sartura */
|
||||
#include "vmlinux.h"
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_tracing.h>
|
||||
|
||||
char LICENSE[] SEC("license") = "Dual BSD/GPL";
|
||||
|
||||
SEC("fentry/do_unlinkat")
|
||||
int BPF_PROG(do_unlinkat, int dfd, struct filename *name)
|
||||
{
|
||||
pid_t pid;
|
||||
|
||||
pid = bpf_get_current_pid_tgid() >> 32;
|
||||
bpf_printk("fentry: pid = %d, filename = %s\n", pid, name->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("fexit/do_unlinkat")
|
||||
int BPF_PROG(do_unlinkat_exit, int dfd, struct filename *name, long ret)
|
||||
{
|
||||
pid_t pid;
|
||||
|
||||
pid = bpf_get_current_pid_tgid() >> 32;
|
||||
bpf_printk("fexit: pid = %d, filename = %s, ret = %ld\n", pid, name->name, ret);
|
||||
return 0;
|
||||
}
|
||||
80
external/libbpf-bootstrap/examples/c/fentry.c
vendored
Normal file
80
external/libbpf-bootstrap/examples/c/fentry.c
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
|
||||
/* Copyright (c) 2021 Sartura
|
||||
* Based on minimal.c by Facebook */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/resource.h>
|
||||
#include <bpf/libbpf.h>
|
||||
#include "fentry.skel.h"
|
||||
|
||||
static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
|
||||
{
|
||||
return vfprintf(stderr, format, args);
|
||||
}
|
||||
|
||||
static void bump_memlock_rlimit(void)
|
||||
{
|
||||
struct rlimit rlim_new = {
|
||||
.rlim_cur = RLIM_INFINITY,
|
||||
.rlim_max = RLIM_INFINITY,
|
||||
};
|
||||
|
||||
if (setrlimit(RLIMIT_MEMLOCK, &rlim_new)) {
|
||||
fprintf(stderr, "Failed to increase RLIMIT_MEMLOCK limit!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static volatile sig_atomic_t stop;
|
||||
|
||||
void sig_int(int signo)
|
||||
{
|
||||
stop = 1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct fentry_bpf *skel;
|
||||
int err;
|
||||
|
||||
/* Set up libbpf errors and debug info callback */
|
||||
libbpf_set_print(libbpf_print_fn);
|
||||
|
||||
/* Bump RLIMIT_MEMLOCK to allow BPF sub-system to do anything */
|
||||
bump_memlock_rlimit();
|
||||
|
||||
/* Open load and verify BPF application */
|
||||
skel = fentry_bpf__open_and_load();
|
||||
if (!skel) {
|
||||
fprintf(stderr, "Failed to open BPF skeleton\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Attach tracepoint handler */
|
||||
err = fentry_bpf__attach(skel);
|
||||
if (err) {
|
||||
fprintf(stderr, "Failed to attach BPF skeleton\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (signal(SIGINT, sig_int) == SIG_ERR) {
|
||||
fprintf(stderr, "can't set signal handler: %s\n", strerror(errno));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
printf("Successfully started! Please run `sudo cat /sys/kernel/debug/tracing/trace_pipe` "
|
||||
"to see output of the BPF programs.\n");
|
||||
|
||||
while (!stop) {
|
||||
fprintf(stderr, ".");
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
fentry_bpf__destroy(skel);
|
||||
return -err;
|
||||
}
|
||||
30
external/libbpf-bootstrap/examples/c/kprobe.bpf.c
vendored
Normal file
30
external/libbpf-bootstrap/examples/c/kprobe.bpf.c
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/* Copyright (c) 2021 Sartura */
|
||||
#include "vmlinux.h"
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_tracing.h>
|
||||
#include <bpf/bpf_core_read.h>
|
||||
|
||||
char LICENSE[] SEC("license") = "Dual BSD/GPL";
|
||||
|
||||
SEC("kprobe/do_unlinkat")
|
||||
int BPF_KPROBE(do_unlinkat, int dfd, struct filename *name)
|
||||
{
|
||||
pid_t pid;
|
||||
const char *filename;
|
||||
|
||||
pid = bpf_get_current_pid_tgid() >> 32;
|
||||
filename = BPF_CORE_READ(name, name);
|
||||
bpf_printk("KPROBE ENTRY pid = %d, filename = %s\n", pid, filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("kretprobe/do_unlinkat")
|
||||
int BPF_KRETPROBE(do_unlinkat_exit, long ret)
|
||||
{
|
||||
pid_t pid;
|
||||
|
||||
pid = bpf_get_current_pid_tgid() >> 32;
|
||||
bpf_printk("KPROBE EXIT: pid = %d, ret = %ld\n", pid, ret);
|
||||
return 0;
|
||||
}
|
||||
80
external/libbpf-bootstrap/examples/c/kprobe.c
vendored
Normal file
80
external/libbpf-bootstrap/examples/c/kprobe.c
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
|
||||
/* Copyright (c) 2021 Sartura
|
||||
* Based on minimal.c by Facebook */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/resource.h>
|
||||
#include <bpf/libbpf.h>
|
||||
#include "kprobe.skel.h"
|
||||
|
||||
static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
|
||||
{
|
||||
return vfprintf(stderr, format, args);
|
||||
}
|
||||
|
||||
static void bump_memlock_rlimit(void)
|
||||
{
|
||||
struct rlimit rlim_new = {
|
||||
.rlim_cur = RLIM_INFINITY,
|
||||
.rlim_max = RLIM_INFINITY,
|
||||
};
|
||||
|
||||
if (setrlimit(RLIMIT_MEMLOCK, &rlim_new)) {
|
||||
fprintf(stderr, "Failed to increase RLIMIT_MEMLOCK limit!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static volatile sig_atomic_t stop;
|
||||
|
||||
static void sig_int(int signo)
|
||||
{
|
||||
stop = 1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct kprobe_bpf *skel;
|
||||
int err;
|
||||
|
||||
/* Set up libbpf errors and debug info callback */
|
||||
libbpf_set_print(libbpf_print_fn);
|
||||
|
||||
/* Bump RLIMIT_MEMLOCK to allow BPF sub-system to do anything */
|
||||
bump_memlock_rlimit();
|
||||
|
||||
/* Open load and verify BPF application */
|
||||
skel = kprobe_bpf__open_and_load();
|
||||
if (!skel) {
|
||||
fprintf(stderr, "Failed to open BPF skeleton\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Attach tracepoint handler */
|
||||
err = kprobe_bpf__attach(skel);
|
||||
if (err) {
|
||||
fprintf(stderr, "Failed to attach BPF skeleton\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (signal(SIGINT, sig_int) == SIG_ERR) {
|
||||
fprintf(stderr, "can't set signal handler: %s\n", strerror(errno));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
printf("Successfully started! Please run `sudo cat /sys/kernel/debug/tracing/trace_pipe` "
|
||||
"to see output of the BPF programs.\n");
|
||||
|
||||
while (!stop) {
|
||||
fprintf(stderr, ".");
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
kprobe_bpf__destroy(skel);
|
||||
return -err;
|
||||
}
|
||||
21
external/libbpf-bootstrap/examples/c/minimal.bpf.c
vendored
Normal file
21
external/libbpf-bootstrap/examples/c/minimal.bpf.c
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/* Copyright (c) 2020 Facebook */
|
||||
#include <linux/bpf.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
|
||||
char LICENSE[] SEC("license") = "Dual BSD/GPL";
|
||||
|
||||
int my_pid = 0;
|
||||
|
||||
SEC("tp/syscalls/sys_enter_write")
|
||||
int handle_tp(void *ctx)
|
||||
{
|
||||
int pid = bpf_get_current_pid_tgid() >> 32;
|
||||
|
||||
if (pid != my_pid)
|
||||
return 0;
|
||||
|
||||
bpf_printk("BPF triggered from PID %d.\n", pid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
74
external/libbpf-bootstrap/examples/c/minimal.c
vendored
Normal file
74
external/libbpf-bootstrap/examples/c/minimal.c
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
|
||||
/* Copyright (c) 2020 Facebook */
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/resource.h>
|
||||
#include <bpf/libbpf.h>
|
||||
#include "minimal.skel.h"
|
||||
|
||||
static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
|
||||
{
|
||||
return vfprintf(stderr, format, args);
|
||||
}
|
||||
|
||||
static void bump_memlock_rlimit(void)
|
||||
{
|
||||
struct rlimit rlim_new = {
|
||||
.rlim_cur = RLIM_INFINITY,
|
||||
.rlim_max = RLIM_INFINITY,
|
||||
};
|
||||
|
||||
if (setrlimit(RLIMIT_MEMLOCK, &rlim_new)) {
|
||||
fprintf(stderr, "Failed to increase RLIMIT_MEMLOCK limit!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct minimal_bpf *skel;
|
||||
int err;
|
||||
|
||||
/* Set up libbpf errors and debug info callback */
|
||||
libbpf_set_print(libbpf_print_fn);
|
||||
|
||||
/* Bump RLIMIT_MEMLOCK to allow BPF sub-system to do anything */
|
||||
bump_memlock_rlimit();
|
||||
|
||||
/* Open BPF application */
|
||||
skel = minimal_bpf__open();
|
||||
if (!skel) {
|
||||
fprintf(stderr, "Failed to open BPF skeleton\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ensure BPF program only handles write() syscalls from our process */
|
||||
skel->bss->my_pid = getpid();
|
||||
|
||||
/* Load & verify BPF programs */
|
||||
err = minimal_bpf__load(skel);
|
||||
if (err) {
|
||||
fprintf(stderr, "Failed to load and verify BPF skeleton\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Attach tracepoint handler */
|
||||
err = minimal_bpf__attach(skel);
|
||||
if (err) {
|
||||
fprintf(stderr, "Failed to attach BPF skeleton\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
printf("Successfully started! Please run `sudo cat /sys/kernel/debug/tracing/trace_pipe` "
|
||||
"to see output of the BPF programs.\n");
|
||||
|
||||
for (;;) {
|
||||
/* trigger our BPF program */
|
||||
fprintf(stderr, ".");
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
minimal_bpf__destroy(skel);
|
||||
return -err;
|
||||
}
|
||||
22
external/libbpf-bootstrap/examples/c/uprobe.bpf.c
vendored
Normal file
22
external/libbpf-bootstrap/examples/c/uprobe.bpf.c
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/* Copyright (c) 2020 Facebook */
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_tracing.h>
|
||||
|
||||
char LICENSE[] SEC("license") = "Dual BSD/GPL";
|
||||
|
||||
SEC("uprobe/func")
|
||||
int BPF_KPROBE(uprobe, int a, int b)
|
||||
{
|
||||
bpf_printk("UPROBE ENTRY: a = %d, b = %d\n", a, b);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("uretprobe/func")
|
||||
int BPF_KRETPROBE(uretprobe, int ret)
|
||||
{
|
||||
bpf_printk("UPROBE EXIT: return = %d\n", ret);
|
||||
return 0;
|
||||
}
|
||||
138
external/libbpf-bootstrap/examples/c/uprobe.c
vendored
Normal file
138
external/libbpf-bootstrap/examples/c/uprobe.c
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
|
||||
/* Copyright (c) 2020 Facebook */
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/resource.h>
|
||||
#include <bpf/libbpf.h>
|
||||
#include "uprobe.skel.h"
|
||||
|
||||
static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
|
||||
{
|
||||
return vfprintf(stderr, format, args);
|
||||
}
|
||||
|
||||
static void bump_memlock_rlimit(void)
|
||||
{
|
||||
struct rlimit rlim_new = {
|
||||
.rlim_cur = RLIM_INFINITY,
|
||||
.rlim_max = RLIM_INFINITY,
|
||||
};
|
||||
|
||||
if (setrlimit(RLIMIT_MEMLOCK, &rlim_new)) {
|
||||
fprintf(stderr, "Failed to increase RLIMIT_MEMLOCK limit!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Find process's base load address. We use /proc/self/maps for that,
|
||||
* searching for the first executable (r-xp) memory mapping:
|
||||
*
|
||||
* 5574fd254000-5574fd258000 r-xp 00002000 fd:01 668759 /usr/bin/cat
|
||||
* ^^^^^^^^^^^^ ^^^^^^^^
|
||||
*
|
||||
* Subtracting that region's offset (4th column) from its absolute start
|
||||
* memory address (1st column) gives us the process's base load address.
|
||||
*/
|
||||
static long get_base_addr() {
|
||||
size_t start, offset;
|
||||
char buf[256];
|
||||
FILE *f;
|
||||
|
||||
f = fopen("/proc/self/maps", "r");
|
||||
if (!f)
|
||||
return -errno;
|
||||
|
||||
while (fscanf(f, "%zx-%*x %s %zx %*[^\n]\n", &start, buf, &offset) == 3) {
|
||||
if (strcmp(buf, "r-xp") == 0) {
|
||||
fclose(f);
|
||||
return start - offset;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* It's a global function to make sure compiler doesn't inline it. */
|
||||
int uprobed_function(int a, int b)
|
||||
{
|
||||
return a + b;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct uprobe_bpf *skel;
|
||||
long base_addr, uprobe_offset;
|
||||
int err, i;
|
||||
|
||||
/* Set up libbpf errors and debug info callback */
|
||||
libbpf_set_print(libbpf_print_fn);
|
||||
|
||||
/* Bump RLIMIT_MEMLOCK to allow BPF sub-system to do anything */
|
||||
bump_memlock_rlimit();
|
||||
|
||||
/* Load and verify BPF application */
|
||||
skel = uprobe_bpf__open_and_load();
|
||||
if (!skel) {
|
||||
fprintf(stderr, "Failed to open and load BPF skeleton\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
base_addr = get_base_addr();
|
||||
if (base_addr < 0) {
|
||||
fprintf(stderr, "Failed to determine process's load address\n");
|
||||
err = base_addr;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* uprobe/uretprobe expects relative offset of the function to attach
|
||||
* to. This offset is relateve to the process's base load address. So
|
||||
* easy way to do this is to take an absolute address of the desired
|
||||
* function and substract base load address from it. If we were to
|
||||
* parse ELF to calculate this function, we'd need to add .text
|
||||
* section offset and function's offset within .text ELF section.
|
||||
*/
|
||||
uprobe_offset = (long)&uprobed_function - base_addr;
|
||||
|
||||
/* Attach tracepoint handler */
|
||||
skel->links.uprobe = bpf_program__attach_uprobe(skel->progs.uprobe,
|
||||
false /* not uretprobe */,
|
||||
0 /* self pid */,
|
||||
"/proc/self/exe",
|
||||
uprobe_offset);
|
||||
err = libbpf_get_error(skel->links.uprobe);
|
||||
if (err) {
|
||||
fprintf(stderr, "Failed to attach uprobe: %d\n", err);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* we can also attach uprobe/uretprobe to any existing or future
|
||||
* processes that use the same binary executable; to do that we need
|
||||
* to specify -1 as PID, as we do here
|
||||
*/
|
||||
skel->links.uretprobe = bpf_program__attach_uprobe(skel->progs.uretprobe,
|
||||
true /* uretprobe */,
|
||||
-1 /* any pid */,
|
||||
"/proc/self/exe",
|
||||
uprobe_offset);
|
||||
err = libbpf_get_error(skel->links.uretprobe);
|
||||
if (err) {
|
||||
fprintf(stderr, "Failed to attach uprobe: %d\n", err);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
printf("Successfully started! Please run `sudo cat /sys/kernel/debug/tracing/trace_pipe` "
|
||||
"to see output of the BPF programs.\n");
|
||||
|
||||
for (i = 0; ; i++) {
|
||||
/* trigger our BPF programs */
|
||||
fprintf(stderr, ".");
|
||||
uprobed_function(i, i + 1);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
uprobe_bpf__destroy(skel);
|
||||
return -err;
|
||||
}
|
||||
100
external/libbpf-bootstrap/examples/c/xmake.lua
vendored
Normal file
100
external/libbpf-bootstrap/examples/c/xmake.lua
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
add_rules("mode.release", "mode.debug")
|
||||
add_rules("platform.linux.bpf")
|
||||
set_license("GPL-2.0")
|
||||
|
||||
if xmake.version():satisfies(">=2.5.7 <=2.5.9") then
|
||||
on_load(function (target)
|
||||
raise("xmake(%s) has a bug preventing BPF source code compilation. Please run `xmake update -f 2.5.6` to revert to v2.5.6 version or upgrade to xmake v2.6.1 that fixed the issue.", xmake.version())
|
||||
end)
|
||||
end
|
||||
|
||||
option("system-libbpf", {showmenu = true, default = false, description = "Use system-installed libbpf"})
|
||||
option("require-bpftool", {showmenu = true, default = false, description = "Require bpftool package"})
|
||||
|
||||
add_requires("libelf", "zlib")
|
||||
if is_plat("android") then
|
||||
add_requires("ndk >=22.x", "argp-standalone")
|
||||
set_toolchains("@ndk", {sdkver = "23"})
|
||||
else
|
||||
add_requires("llvm >=10.x")
|
||||
set_toolchains("@llvm")
|
||||
add_requires("linux-headers")
|
||||
end
|
||||
|
||||
add_includedirs("../../vmlinux")
|
||||
|
||||
-- we can run `xmake f --require-bpftool=y` to pull bpftool from xmake-repo repository
|
||||
if has_config("require-bpftool") then
|
||||
add_requires("linux-tools", {configs = {bpftool = true}})
|
||||
add_packages("linux-tools")
|
||||
else
|
||||
before_build(function (target)
|
||||
os.addenv("PATH", path.join(os.scriptdir(), "..", "..", "tools"))
|
||||
end)
|
||||
end
|
||||
|
||||
-- we use the vendored libbpf sources for libbpf-bootstrap.
|
||||
-- for some projects you may want to use the system-installed libbpf, so you can run `xmake f --system-libbpf=y`
|
||||
if has_config("system-libbpf") then
|
||||
add_requires("libbpf", {system = true})
|
||||
else
|
||||
target("libbpf")
|
||||
set_kind("static")
|
||||
set_basename("bpf")
|
||||
add_files("../../libbpf/src/*.c")
|
||||
add_includedirs("../../libbpf/include")
|
||||
add_includedirs("../../libbpf/include/uapi", {public = true})
|
||||
add_includedirs("$(buildir)", {interface = true})
|
||||
add_configfiles("../../libbpf/src/(*.h)", {prefixdir = "bpf"})
|
||||
add_packages("libelf", "zlib")
|
||||
if is_plat("android") then
|
||||
add_defines("__user=", "__force=", "__poll_t=uint32_t")
|
||||
end
|
||||
end
|
||||
|
||||
target("minimal")
|
||||
set_kind("binary")
|
||||
add_files("minimal*.c")
|
||||
add_packages("linux-headers")
|
||||
if not has_config("system-libbpf") then
|
||||
add_deps("libbpf")
|
||||
end
|
||||
|
||||
target("bootstrap")
|
||||
set_kind("binary")
|
||||
add_files("bootstrap*.c")
|
||||
add_packages("linux-headers")
|
||||
if not has_config("system-libbpf") then
|
||||
add_deps("libbpf")
|
||||
end
|
||||
if is_plat("android") then
|
||||
add_packages("argp-standalone")
|
||||
end
|
||||
|
||||
target("fentry")
|
||||
set_kind("binary")
|
||||
add_files("fentry*.c")
|
||||
add_packages("linux-headers")
|
||||
if not has_config("system-libbpf") then
|
||||
add_deps("libbpf")
|
||||
end
|
||||
|
||||
target("uprobe")
|
||||
set_kind("binary")
|
||||
add_files("uprobe*.c")
|
||||
add_packages("linux-headers")
|
||||
if not has_config("system-libbpf") then
|
||||
add_deps("libbpf")
|
||||
end
|
||||
|
||||
target("kprobe")
|
||||
set_kind("binary")
|
||||
add_files("kprobe*.c")
|
||||
add_packages("linux-headers")
|
||||
if not has_config("system-libbpf") then
|
||||
add_deps("libbpf")
|
||||
end
|
||||
if is_plat("android") then
|
||||
-- TODO we need fix vmlinux.h to support android
|
||||
set_default(false)
|
||||
end
|
||||
Reference in New Issue
Block a user