Commit d7c431ca authored by Kumar Kartikeya Dwivedi's avatar Kumar Kartikeya Dwivedi Committed by Alexei Starovoitov
Browse files

bpf: Add dump_stack() analogue to print to BPF stderr



Introduce a kernel function which is the analogue of dump_stack()
printing some useful information and the stack trace. This is not
exposed to BPF programs yet, but can be made available in the future.

When we have a program counter for a BPF program in the stack trace,
also additionally output the filename and line number to make the trace
helpful. The rest of the trace can be passed into ./decode_stacktrace.sh
to obtain the line numbers for kernel symbols.

Reviewed-by: default avatarEmil Tsalapatis <emil@etsalapatis.com>
Signed-off-by: default avatarKumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/r/20250703204818.925464-7-memxor@gmail.com


Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent f0c53fd4
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -3616,8 +3616,10 @@ __printf(2, 3)
int bpf_stream_stage_printk(struct bpf_stream_stage *ss, const char *fmt, ...);
int bpf_stream_stage_commit(struct bpf_stream_stage *ss, struct bpf_prog *prog,
			    enum bpf_stream_id stream_id);
int bpf_stream_stage_dump_stack(struct bpf_stream_stage *ss);

#define bpf_stream_printk(ss, ...) bpf_stream_stage_printk(&ss, __VA_ARGS__)
#define bpf_stream_dump_stack(ss) bpf_stream_stage_dump_stack(&ss)

#define bpf_stream_stage(ss, prog, stream_id, expr)            \
	({                                                     \
+48 −0
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@
/* Copyright (c) 2025 Meta Platforms, Inc. and affiliates. */

#include <linux/bpf.h>
#include <linux/filter.h>
#include <linux/bpf_mem_alloc.h>
#include <linux/percpu.h>
#include <linux/refcount.h>
@@ -476,3 +477,50 @@ int bpf_stream_stage_commit(struct bpf_stream_stage *ss, struct bpf_prog *prog,
	llist_add_batch(head, tail, &stream->log);
	return 0;
}

struct dump_stack_ctx {
	struct bpf_stream_stage *ss;
	int err;
};

static bool dump_stack_cb(void *cookie, u64 ip, u64 sp, u64 bp)
{
	struct dump_stack_ctx *ctxp = cookie;
	const char *file = "", *line = "";
	struct bpf_prog *prog;
	int num, ret;

	rcu_read_lock();
	prog = bpf_prog_ksym_find(ip);
	rcu_read_unlock();
	if (prog) {
		ret = bpf_prog_get_file_line(prog, ip, &file, &line, &num);
		if (ret < 0)
			goto end;
		ctxp->err = bpf_stream_stage_printk(ctxp->ss, "%pS\n  %s @ %s:%d\n",
						    (void *)ip, line, file, num);
		return !ctxp->err;
	}
end:
	ctxp->err = bpf_stream_stage_printk(ctxp->ss, "%pS\n", (void *)ip);
	return !ctxp->err;
}

int bpf_stream_stage_dump_stack(struct bpf_stream_stage *ss)
{
	struct dump_stack_ctx ctx = { .ss = ss };
	int ret;

	ret = bpf_stream_stage_printk(ss, "CPU: %d UID: %d PID: %d Comm: %s\n",
				      raw_smp_processor_id(), __kuid_val(current_real_cred()->euid),
				      current->pid, current->comm);
	if (ret)
		return ret;
	ret = bpf_stream_stage_printk(ss, "Call trace:\n");
	if (ret)
		return ret;
	arch_bpf_stack_walk(dump_stack_cb, &ctx);
	if (ctx.err)
		return ctx.err;
	return bpf_stream_stage_printk(ss, "\n");
}