Skip to content

Commit

Permalink
Remove synthetic unwinder error frames from agent and instead
Browse files Browse the repository at this point in the history
generate them in the unwinder with more context.

Also don't throw away frames when we can't get the process info.

If frame pointer unwinding fails still tail call interpter unwinder

luajit stack unwinding support

Works with openresty and luajit with caveats. lua_State is looked up via
uprobes on lua_pcall and lua_resume.  If uprobes aren't enabled an
attempt will be made to look up lua_State via nginx_lua_co_ctx object
which seems to work well for openresty but isn't well tested.

Fixes: parca-dev#1889

cleanup

fix lua runtime detection

[pre-commit.ci lite] apply automatic fixes

switch from L to G tracking which should be more reliable

look below rsp

make format

fix rebase issues

lua 5.10 kernel fixes

make lua unwinder work in more cases

cleanup

wip

get cur_L and jit_base from assembly

more fixes

fix instruction limits errors

cleanup
  • Loading branch information
gnurizen committed Jul 2, 2024
1 parent 4888a19 commit b032c9f
Show file tree
Hide file tree
Showing 33 changed files with 4,009 additions and 68 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/test-integration-amd64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ jobs:
if: ${{ always() }}
run: GOMODCACHE=$(go env GOMODCACHE) make GO=`which go` test/integration/ruby

- name: Integration Tests (Lua)
if: ${{ always() }}
run: GOMODCACHE=$(go env GOMODCACHE) make GO=`which go` test/integration/lua

- name: Integration Tests (Java)
if: ${{ always() }}
continue-on-error: true
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/test-integration-arm64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ jobs:
if: ${{ always() }}
run: GOMODCACHE=$(go env GOMODCACHE) make GO=`which go` test/integration/ruby

- name: Integration Tests (Lua)
if: ${{ always() }}
run: GOMODCACHE=$(go env GOMODCACHE) make GO=`which go` test/integration/lua

- name: Integration Tests (Java)
if: ${{ always() }}
continue-on-error: true
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,5 @@ result*

# java
*.class

.vscode
11 changes: 11 additions & 0 deletions Dockerfile.luapre
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM gcr.io/distroless/static@sha256:41972110a1c1a5c0b6adb283e8aa092c43c31f7c5d79b8656fbffff2c3e61f05

LABEL \
org.opencontainers.image.source="https://github.com/parca-dev/parca-agent" \
org.opencontainers.image.url="https://github.com/parca-dev/parca-agent" \
org.opencontainers.image.description="eBPF based always-on profiler auto-discovering targets in Kubernetes and systemd, zero code changes or restarts needed!" \
org.opencontainers.image.licenses="Apache-2.0"


COPY --chown=0:0 parca-agent /bin/
CMD ["/bin/parca-agent"]
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ OUT_BPF := $(OUT_BPF_DIR)/native.bpf.o
OUT_RBPERF := $(OUT_BPF_DIR)/rbperf.bpf.o
OUT_PYPERF := $(OUT_BPF_DIR)/pyperf.bpf.o
OUT_JVM := $(OUT_BPF_DIR)/jvm.bpf.o
OUT_LUA := $(OUT_BPF_DIR)/lua.bpf.o
OUT_BPF_CONTAINED_DIR := pkg/contained/bpf/$(ARCH)
OUT_PID_NAMESPACE := $(OUT_BPF_CONTAINED_DIR)/pid_namespace.bpf.o

Expand Down Expand Up @@ -167,6 +168,7 @@ $(OUT_BPF): $(BPF_SRC) libbpf | $(OUT_DIR)
cp bpf/out/$(ARCH)/rbperf.bpf.o $(OUT_RBPERF)
cp bpf/out/$(ARCH)/pyperf.bpf.o $(OUT_PYPERF)
cp bpf/out/$(ARCH)/jvm.bpf.o $(OUT_JVM)
cp bpf/out/$(ARCH)/lua.bpf.o $(OUT_LUA)
cp bpf/out/$(ARCH)/pid_namespace.bpf.o $(OUT_PID_NAMESPACE)
else
$(OUT_BPF): $(DOCKER_BUILDER) | $(OUT_DIR)
Expand Down Expand Up @@ -248,6 +250,9 @@ test/integration/ruby: $(GO_SRC) $(LIBBPF_HEADERS) $(LIBBPF_OBJ) bpf
test/integration/java: $(GO_SRC) $(LIBBPF_HEADERS) $(LIBBPF_OBJ) bpf
sudo --preserve-env=CI,C_INCLUDE_PATH,LIBRARY_PATH,PKG_CONFIG_PATH $(GO_ENV) $(CGO_ENV) $(GO) test $(SANITIZERS) -v ./test/integration/java -count=1

test/integration/lua: $(GO_SRC) $(LIBBPF_HEADERS) $(LIBBPF_OBJ) bpf
sudo --preserve-env=CI,C_INCLUDE_PATH,LIBRARY_PATH,PKG_CONFIG_PATH $(GO_ENV) $(CGO_ENV) $(GO) test $(SANITIZERS) -v ./test/integration/lua -count=1

.PHONY: integration-stress
integration-stress:
sudo --preserve-env=CI $(GO_ENV) $(CGO_ENV) $(GO) test $(SANITIZERS) ./test/integration/... -count=5
Expand Down
22 changes: 19 additions & 3 deletions bpf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ OUT_BPF := $(OUT_BPF_DIR)/native.bpf.o
OUT_RBPERF := $(OUT_BPF_DIR)/rbperf.bpf.o
OUT_PYPERF := $(OUT_BPF_DIR)/pyperf.bpf.o
OUT_JVM := $(OUT_BPF_DIR)/jvm.bpf.o
OUT_LUA := $(OUT_BPF_DIR)/lua.bpf.o
OUT_PID_NAMESPACE_DETECTOR := $(OUT_BPF_DIR)/pid_namespace.bpf.o
BPF_BUNDLE := $(OUT_DIR)/parca-agent.bpf.tar.gz

Expand All @@ -28,6 +29,7 @@ BPF_SRC := unwinders/native.bpf.c unwinders/go_runtime.h
RBPERF_SRC := unwinders/rbperf.bpf.c
PYPERF_SRC := unwinders/pyperf.bpf.c
JVM_SRC := unwinders/jvm.bpf.c
LUA_SRC := unwinders/lua.bpf.c
OUT_PID_NAMESPACE_DETECTOR_SRC := pid_namespace.bpf.c
BPF_INCLUDES := unwinders/

Expand All @@ -46,11 +48,11 @@ format: c/fmt

.PHONY: c/fmt
c/fmt:
$(CMD_CLANG_FORMAT) -i --style=file $(BPF_HEADERS) $(BPF_SRC) $(RBPERF_SRC) $(PYPERF_SRC) $(JVM_SRC) $(OUT_PID_NAMESPACE_DETECTOR_SRC)
$(CMD_CLANG_FORMAT) -i --style=file $(BPF_HEADERS) $(BPF_SRC) $(RBPERF_SRC) $(PYPERF_SRC) $(JVM_SRC) $(LUA_SRC) $(OUT_PID_NAMESPACE_DETECTOR_SRC)

.PHONY: format-check
format-check:
$(CMD_CLANG_FORMAT) --dry-run -Werror --style=file $(BPF_HEADERS) $(BPF_SRC) $(RBPERF_SRC) $(PYPERF_SRC) $(JVM_SRC) $(OUT_PID_NAMESPACE_DETECTOR_SRC)
$(CMD_CLANG_FORMAT) --dry-run -Werror --style=file $(BPF_HEADERS) $(BPF_SRC) $(RBPERF_SRC) $(PYPERF_SRC) $(JVM_SRC) $(LUA_SRC) $(OUT_PID_NAMESPACE_DETECTOR_SRC)

# compilation options:
BPF_CFLAGS = -Wno-address-of-packed-member \
Expand All @@ -76,7 +78,7 @@ BPF_CFLAGS = -Wno-address-of-packed-member \

# tasks:
.PHONY: clang
clang: $(OUT_BPF) $(OUT_RBPERF) $(OUT_PYPERF) $(OUT_JVM) $(OUT_PID_NAMESPACE_DETECTOR)
clang: $(OUT_BPF) $(OUT_RBPERF) $(OUT_PYPERF) $(OUT_JVM) $(OUT_LUA) $(OUT_PID_NAMESPACE_DETECTOR)

bpf_bundle_dir := $(OUT_DIR)/parca-agent.bpf
$(BPF_BUNDLE): $(BPF_SRC) $(LIBBPF_HEADERS)/bpf $(BPF_HEADERS)
Expand Down Expand Up @@ -152,3 +154,17 @@ $(OUT_JVM): $(JVM_SRC) $(LIBBPF_HEADERS) $(BPF_HEADERS) | $(OUT_DIR)
-O2 -emit-llvm -c -g $< -o $(@:.o=.ll)
$(CMD_LLC) -march=bpf -filetype=obj -o $@ $(@:.o=.ll)
rm $(@:.o=.ll)

$(OUT_LUA): $(LUA_SRC) $(LIBBPF_HEADERS) $(BPF_HEADERS) | $(OUT_DIR)
mkdir -p $(OUT_BPF_DIR)
$(CMD_CC) -S \
-D__BPF_TRACING__ \
-D__KERNEL__ \
-D__TARGET_ARCH_$(SHORT_ARCH) \
-I $(VMLINUX_INCLUDE_PATH) \
-I $(LIBBPF_HEADERS) \
-I $(BPF_INCLUDES) \
$(BPF_CFLAGS) \
-O2 -emit-llvm -c -g $< -o $(@:.o=.ll)
$(CMD_LLC) -march=bpf -filetype=obj -o $@ $(@:.o=.ll)
rm $(@:.o=.ll)
1 change: 1 addition & 0 deletions bpf/unwinders/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ typedef struct {
#define RUBY_UNWINDER_PROGRAM_ID 1
#define PYTHON_UNWINDER_PROGRAM_ID 2
#define JAVA_UNWINDER_PROGRAM_ID 3
#define LUA_UNWINDER_PROGRAM_ID 4

// Use ERROR_SAMPLE to report one stack frame of an error message as an interpreter symbol.
// class -> msg provided in macro
Expand Down
Loading

0 comments on commit b032c9f

Please sign in to comment.