Skip to content

Commit d7c431c

Browse files
kkdwivediAlexei Starovoitov
authored andcommitted
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: Emil Tsalapatis <[email protected]> Signed-off-by: Kumar Kartikeya Dwivedi <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent f0c53fd commit d7c431c

File tree

2 files changed

+50
-0
lines changed

2 files changed

+50
-0
lines changed

include/linux/bpf.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3616,8 +3616,10 @@ __printf(2, 3)
36163616
int bpf_stream_stage_printk(struct bpf_stream_stage *ss, const char *fmt, ...);
36173617
int bpf_stream_stage_commit(struct bpf_stream_stage *ss, struct bpf_prog *prog,
36183618
enum bpf_stream_id stream_id);
3619+
int bpf_stream_stage_dump_stack(struct bpf_stream_stage *ss);
36193620

36203621
#define bpf_stream_printk(ss, ...) bpf_stream_stage_printk(&ss, __VA_ARGS__)
3622+
#define bpf_stream_dump_stack(ss) bpf_stream_stage_dump_stack(&ss)
36213623

36223624
#define bpf_stream_stage(ss, prog, stream_id, expr) \
36233625
({ \

kernel/bpf/stream.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
/* Copyright (c) 2025 Meta Platforms, Inc. and affiliates. */
33

44
#include <linux/bpf.h>
5+
#include <linux/filter.h>
56
#include <linux/bpf_mem_alloc.h>
67
#include <linux/percpu.h>
78
#include <linux/refcount.h>
@@ -476,3 +477,50 @@ int bpf_stream_stage_commit(struct bpf_stream_stage *ss, struct bpf_prog *prog,
476477
llist_add_batch(head, tail, &stream->log);
477478
return 0;
478479
}
480+
481+
struct dump_stack_ctx {
482+
struct bpf_stream_stage *ss;
483+
int err;
484+
};
485+
486+
static bool dump_stack_cb(void *cookie, u64 ip, u64 sp, u64 bp)
487+
{
488+
struct dump_stack_ctx *ctxp = cookie;
489+
const char *file = "", *line = "";
490+
struct bpf_prog *prog;
491+
int num, ret;
492+
493+
rcu_read_lock();
494+
prog = bpf_prog_ksym_find(ip);
495+
rcu_read_unlock();
496+
if (prog) {
497+
ret = bpf_prog_get_file_line(prog, ip, &file, &line, &num);
498+
if (ret < 0)
499+
goto end;
500+
ctxp->err = bpf_stream_stage_printk(ctxp->ss, "%pS\n %s @ %s:%d\n",
501+
(void *)ip, line, file, num);
502+
return !ctxp->err;
503+
}
504+
end:
505+
ctxp->err = bpf_stream_stage_printk(ctxp->ss, "%pS\n", (void *)ip);
506+
return !ctxp->err;
507+
}
508+
509+
int bpf_stream_stage_dump_stack(struct bpf_stream_stage *ss)
510+
{
511+
struct dump_stack_ctx ctx = { .ss = ss };
512+
int ret;
513+
514+
ret = bpf_stream_stage_printk(ss, "CPU: %d UID: %d PID: %d Comm: %s\n",
515+
raw_smp_processor_id(), __kuid_val(current_real_cred()->euid),
516+
current->pid, current->comm);
517+
if (ret)
518+
return ret;
519+
ret = bpf_stream_stage_printk(ss, "Call trace:\n");
520+
if (ret)
521+
return ret;
522+
arch_bpf_stack_walk(dump_stack_cb, &ctx);
523+
if (ctx.err)
524+
return ctx.err;
525+
return bpf_stream_stage_printk(ss, "\n");
526+
}

0 commit comments

Comments
 (0)