-
-
Notifications
You must be signed in to change notification settings - Fork 84
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
runtime: implement userspace USDT (#139)
* Place holder * Update * Add usdt example * Fix fd allocation * Update llvm-jit * Fix CI * Full cookie support * Update CI * Fix CI * Fix CI * update README
- Loading branch information
1 parent
aeeb6d6
commit 83064ae
Showing
27 changed files
with
452 additions
and
75 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
.vscode | ||
package.json | ||
*.o | ||
*.skel.json | ||
*.skel.yaml | ||
package.yaml | ||
ecli | ||
.output | ||
test | ||
victim | ||
usdt_minimal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) | ||
OUTPUT := .output | ||
CLANG ?= clang | ||
LIBBPF_SRC := $(abspath ../../third_party/libbpf/src) | ||
BPFTOOL_SRC := $(abspath ../../third_party/bpftool/src) | ||
LIBBPF_OBJ := $(abspath $(OUTPUT)/libbpf.a) | ||
BPFTOOL_OUTPUT ?= $(abspath $(OUTPUT)/bpftool) | ||
BPFTOOL ?= $(BPFTOOL_OUTPUT)/bootstrap/bpftool | ||
ARCH ?= $(shell uname -m | sed 's/x86_64/x86/' \ | ||
| sed 's/arm.*/arm/' \ | ||
| sed 's/aarch64/arm64/' \ | ||
| sed 's/ppc64le/powerpc/' \ | ||
| sed 's/mips.*/mips/' \ | ||
| sed 's/riscv64/riscv/' \ | ||
| sed 's/loongarch64/loongarch/') | ||
VMLINUX := ../../third_party/vmlinux/$(ARCH)/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../../third_party/libbpf/include/uapi -I$(dir $(VMLINUX)) | ||
CFLAGS := -g -Wall | ||
ALL_LDFLAGS := $(LDFLAGS) $(EXTRA_LDFLAGS) | ||
|
||
APPS = usdt_minimal | ||
|
||
CARGO ?= $(shell which cargo) | ||
ifeq ($(strip $(CARGO)),) | ||
BZS_APPS := | ||
else | ||
BZS_APPS := # profile | ||
APPS += $(BZS_APPS) | ||
# Required by libblazesym | ||
ALL_LDFLAGS += -lrt -ldl -lpthread -lm | ||
endif | ||
|
||
# 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 | ||
|
||
define allow-override | ||
$(if $(or $(findstring environment,$(origin $(1))),\ | ||
$(findstring command line,$(origin $(1)))),,\ | ||
$(eval $(1) = $(2))) | ||
endef | ||
|
||
$(call allow-override,CC,$(CROSS_COMPILE)cc) | ||
$(call allow-override,LD,$(CROSS_COMPILE)ld) | ||
|
||
.PHONY: all | ||
all: $(APPS) victim | ||
|
||
victim: victim.cpp | ||
g++ victim.cpp -o victim -Wall -g | ||
|
||
.PHONY: clean | ||
clean: | ||
$(call msg,CLEAN) | ||
$(Q)rm -rf $(OUTPUT) $(APPS) | ||
|
||
$(OUTPUT) $(OUTPUT)/libbpf $(BPFTOOL_OUTPUT): | ||
$(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 bpftool | ||
$(BPFTOOL): | $(BPFTOOL_OUTPUT) | ||
$(call msg,BPFTOOL,$@) | ||
$(Q)$(MAKE) ARCH= CROSS_COMPILE= OUTPUT=$(BPFTOOL_OUTPUT)/ -C $(BPFTOOL_SRC) bootstrap | ||
|
||
|
||
$(LIBBLAZESYM_SRC)/target/release/libblazesym.a:: | ||
$(Q)cd $(LIBBLAZESYM_SRC) && $(CARGO) build --features=cheader,dont-generate-test-files --release | ||
|
||
$(LIBBLAZESYM_OBJ): $(LIBBLAZESYM_SRC)/target/release/libblazesym.a | $(OUTPUT) | ||
$(call msg,LIB, $@) | ||
$(Q)cp $(LIBBLAZESYM_SRC)/target/release/libblazesym.a $@ | ||
|
||
$(LIBBLAZESYM_HEADER): $(LIBBLAZESYM_SRC)/target/release/libblazesym.a | $(OUTPUT) | ||
$(call msg,LIB,$@) | ||
$(Q)cp $(LIBBLAZESYM_SRC)/target/release/blazesym.h $@ | ||
|
||
# Build BPF code | ||
$(OUTPUT)/%.bpf.o: %.bpf.c $(LIBBPF_OBJ) $(wildcard %.h) $(VMLINUX) | $(OUTPUT) $(BPFTOOL) | ||
$(call msg,BPF,$@) | ||
$(Q)$(CLANG) -g -O2 -target bpf -D__TARGET_ARCH_$(ARCH) \ | ||
$(INCLUDES) $(CLANG_BPF_SYS_INCLUDES) \ | ||
-c $(filter %.c,$^) -o $(patsubst %.bpf.o,%.tmp.bpf.o,$@) | ||
$(Q)$(BPFTOOL) gen object $@ $(patsubst %.bpf.o,%.tmp.bpf.o,$@) | ||
|
||
# Generate BPF skeletons | ||
$(OUTPUT)/%.skel.h: $(OUTPUT)/%.bpf.o | $(OUTPUT) $(BPFTOOL) | ||
$(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 $@ | ||
|
||
$(patsubst %,$(OUTPUT)/%.o,$(BZS_APPS)): $(LIBBLAZESYM_HEADER) | ||
|
||
$(BZS_APPS): $(LIBBLAZESYM_OBJ) | ||
|
||
# Build application binary | ||
$(APPS): %: $(OUTPUT)/%.o $(LIBBPF_OBJ) | $(OUTPUT) | ||
$(call msg,BINARY,$@) | ||
$(Q)$(CC) $(CFLAGS) $^ $(ALL_LDFLAGS) -lelf -lz -o $@ | ||
|
||
# delete failed targets | ||
.DELETE_ON_ERROR: | ||
|
||
# keep intermediate (.skel.h, .bpf.o, etc) targets | ||
.SECONDARY: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# USDT example | ||
|
||
This is an example demonstrating USDT. The ebpf program will be hooked onto the tracepoint named `probe1`, and print arguments through `bpf_printk` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
|
||
#include <vmlinux.h> | ||
#include <bpf/bpf_helpers.h> | ||
#include <bpf/bpf_tracing.h> | ||
#include <bpf/usdt.bpf.h> | ||
|
||
SEC("usdt") | ||
int BPF_USDT(simple_probe, int x, int y, int z) | ||
{ | ||
bpf_printk("bpf: %d + %d = %d\n", x, y, z); | ||
return 0; | ||
} | ||
|
||
char LICENSE[] SEC("license") = "Dual BSD/GPL"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) | ||
/* Copyright (c) 2022 Hengqi Chen */ | ||
#include <signal.h> | ||
#include <unistd.h> | ||
#include <setjmp.h> | ||
#include <linux/limits.h> | ||
#include ".output/usdt_minimal.skel.h" | ||
|
||
static volatile sig_atomic_t exiting; | ||
|
||
static void sig_int(int signo) | ||
{ | ||
exiting = 1; | ||
} | ||
|
||
static int libbpf_print_fn(enum libbpf_print_level level, const char *format, | ||
va_list args) | ||
{ | ||
return vfprintf(stderr, format, args); | ||
} | ||
|
||
int main(int argc, char **argv) | ||
{ | ||
struct usdt_minimal_bpf *skel; | ||
int err; | ||
|
||
libbpf_set_print(libbpf_print_fn); | ||
|
||
skel = usdt_minimal_bpf__open(); | ||
if (!skel) { | ||
fprintf(stderr, "Failed to open BPF skeleton\n"); | ||
return 1; | ||
} | ||
|
||
err = usdt_minimal_bpf__load(skel); | ||
if (!skel) { | ||
fprintf(stderr, "Failed to load BPF skeleton\n"); | ||
return 1; | ||
} | ||
|
||
skel->links.simple_probe = | ||
bpf_program__attach_usdt(skel->progs.simple_probe, -1, | ||
"./victim", "victim", "probe1", NULL); | ||
if (!skel->links.simple_probe) { | ||
err = errno; | ||
fprintf(stderr, | ||
"Failed to attach BPF program `usdt_manual_attach`: %d\n", | ||
err); | ||
goto cleanup; | ||
} | ||
|
||
if (signal(SIGINT, sig_int) == SIG_ERR) { | ||
err = errno; | ||
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 (!exiting) { | ||
/* trigger our BPF programs */ | ||
fprintf(stderr, "."); | ||
sleep(1); | ||
} | ||
|
||
cleanup: | ||
usdt_minimal_bpf__destroy(skel); | ||
return -err; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
#include <iostream> | ||
#include <ostream> | ||
#include <sys/sdt.h> | ||
#include <random> | ||
#include <thread> | ||
using namespace std::chrono_literals; | ||
int main() | ||
{ | ||
std::mt19937 gen; | ||
gen.seed(std::random_device()()); | ||
std::uniform_int_distribution<int> rand(1, 1e6); | ||
while (true) { | ||
int x = rand(gen); | ||
int y = rand(gen); | ||
int z = x + y; | ||
DTRACE_PROBE3(victim, probe1, x, y, z); | ||
std::cout << x << " + " << y << " = " << z << std::endl; | ||
int x1 = y; | ||
int y1 = x; | ||
DTRACE_PROBE3(victim, probe1, x1, y1, z); | ||
std::this_thread::sleep_for(1s); | ||
} | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.