Skip to content

libbpf-tools/stackcount: Add libbpf-based stackcount tool#5410

Open
ismhong wants to merge 1 commit intoiovisor:masterfrom
ismhong:add_libbpf_stackcount
Open

libbpf-tools/stackcount: Add libbpf-based stackcount tool#5410
ismhong wants to merge 1 commit intoiovisor:masterfrom
ismhong:add_libbpf_stackcount

Conversation

@ismhong
Copy link
Copy Markdown
Contributor

@ismhong ismhong commented Oct 15, 2025

This commit introduces libbpf version of stackcount tool based on BCC Python based stackcount. The usage is the same with original one.

Change-Id: I1b057cded14f5803ebba9840837d903df25257f9

This commit introduces libbpf version of stackcount tool based on BCC
Python based stackcount. The usage is the same with original one.

Change-Id: I1b057cded14f5803ebba9840837d903df25257f9
Signed-off-by: Ism Hong <ism.hong@gmail.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new stackcount tool under libbpf-tools/ implemented with libbpf CO-RE, intended to mirror the BCC stackcount CLI for counting events and aggregating user/kernel stack traces.

Changes:

  • Introduce new userspace implementation (stackcount.c) with argp CLI, probe attach logic, and stack printing.
  • Introduce new BPF program (stackcount.bpf.c) and shared header (stackcount.h) for stack-id aggregation in a hash map.
  • Wire the new tool into libbpf-tools/Makefile and .gitignore.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
libbpf-tools/stackcount.c New userspace CLI, attach logic (kprobe/tp/uprobe), and stack aggregation/printing.
libbpf-tools/stackcount.bpf.c New BPF program to collect stack IDs and increment counts.
libbpf-tools/stackcount.h Shared key struct/constants between userspace and BPF.
libbpf-tools/Makefile Adds stackcount to the build list.
libbpf-tools/.gitignore Ignores the built stackcount binary.

Comment thread libbpf-tools/stackcount.c
Comment on lines +230 to +233
static __u64 *stack;
size_t i;

stack = calloc(env.perf_max_stack_depth, sizeof(__u64));
Comment thread libbpf-tools/stackcount.c
Comment on lines +103 to +106
{ "timestamp", 'T', NULL, 0, "Include timestamp on output", 0 },
{ "regexp", 'r', NULL, 0, "Use regular expressions. "
"Default is '*' wildcards only.", 0 },
{ "offset", 's', NULL, 0, "Show address offsets", 0 },
Comment thread libbpf-tools/stackcount.c
Comment on lines +92 to +94
" ./stackcount -p 185 c:malloc # count stacks for malloc in PID 185"
" ./stackcount t:sched:sched_fork # count stacks for sched_fork tracepoint"
" ./stackcount -p 185 u:node:* # count stacks for all USDT probes in node"
Comment thread libbpf-tools/stackcount.c
Comment on lines +483 to +490
cgroup_fd = open(env.cgroup_path, O_RDONLY);
if (cgroup_fd < 0) {
warn("failed to open cgroup path: %s\n", env.cgroup_path);
goto cleanup;
}
bpf_program__attach_cgroup(skel->progs.kprobe_prog, cgroup_fd);
bpf_program__attach_cgroup(skel->progs.tp_prog, cgroup_fd);
bpf_program__attach_cgroup(skel->progs.uprobe_prog, cgroup_fd);
Comment thread libbpf-tools/stackcount.c
for (i = 0; i < items_size; i++) {
if (env.folded) {
// print folded stack output
printf("%s;", items[i].key.name);
Comment thread libbpf-tools/stackcount.c
const struct count_info *A = a;
const struct count_info *B = b;

return A->value - B->value;
Comment thread libbpf-tools/stackcount.c
Comment on lines +366 to +370
lookup_key = NULL;
while (bpf_map_get_next_key(counts_fd, lookup_key, &next_key) == 0) {
bpf_map_delete_elem(counts_fd, &next_key);
lookup_key = &next_key;
}
Comment thread libbpf-tools/stackcount.c

if (strcmp(probe_type, "t") == 0) {
char *category = strtok(NULL, ":");
char *event = strtok(NULL, ":");
Comment thread libbpf-tools/stackcount.c
Comment on lines +563 to +567
while (!exiting) {
sleep(env.interval);
if (env.duration-- == 0)
break;
print_stacks(skel, ksyms, usyms);
Comment on lines +12 to +29
const volatile int target_pid = 0;
const volatile int target_cpu = -1;
const volatile bool kernel_stacks_only = false;
const volatile bool user_stacks_only = false;
const volatile bool per_pid = false;

struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, MAX_ENTRIES);
__type(key, struct key_t);
__type(value, u64);
} counts SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_STACK_TRACE);
__type(key, u32);
} stack_traces SEC(".maps");

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants