Skip to content

Helper function bpf_get_stackid

v4.6

Definition

Copyright (c) 2015 The Libbpf Authors. All rights reserved.

Walk a user or a kernel stack and return its id. To achieve this, the helper needs ctx, which is a pointer to the context on which the tracing program is executed, and a pointer to a map of type BPF_MAP_TYPE_STACK_TRACE.

The last argument, flags, holds the number of stack frames to skip (from 0 to 255), masked with BPF_F_SKIP_FIELD_MASK. The next bits can be used to set a combination of the following flags:

BPF_F_USER_STACK

    Collect a user space stack instead of a kernel stack.

BPF_F_FAST_STACK_CMP

    Compare stacks by hash only.

BPF_F_REUSE_STACKID

    If two different stacks hash into the same stackid, discard the old one.

The stack id retrieved is a 32 bit long integer handle which can be further combined with other data (including other stack ids) and used as a key into maps. This can be useful for generating a variety of graphs (such as flame graphs or off-cpu graphs).

For walking a stack, this helper is an improvement over bpf_probe_read(), which can be used with unrolled loops but is not efficient and consumes a lot of eBPF instructions. Instead, bpf_get_stackid() can collect up to PERF_MAX_STACK_DEPTH both kernel and user frames. Note that this limit can be controlled with the sysctl program, and that it should be manually increased in order to profile long user stacks (such as stacks for Java programs). To do so, use:

# sysctl kernel.perf_event_max_stack=<new value>

Returns

The positive or null stack id on success, or a negative error in case of failure.

static long (* const bpf_get_stackid)(void *ctx, void *map, __u64 flags) = (void *) 27;

Usage

Call bpf_get_stackid to retrieve the stack id of the context in which the program is running, specifying as arguments:

  • ctx, the pointer to the current context on which the program is executing
  • bpf_map, the pointer to a map of type BPF_MAP_TYPE_STACK_TRACE
  • flags, the flags bitmap
long bpf_get_stackid(void *ctx, struct bpf_map *map, u64 flags)

Program types

This helper call can be used in the following program types:

Example

#include <bpf/bpf_helpers.h>

struct {
    __uint(type, BPF_MAP_TYPE_STACK_TRACE);
    __uint(key_size, sizeof(u32));
    __uint(value_size, PERF_MAX_STACK_DEPTH * sizeof(u64));
    __uint(max_entries, 10000);
} stack_traces SEC(".maps");

SEC("perf_event")
int print_stack_ids(struct bpf_perf_event_data *ctx)
{
    char fmt[] = "kern_stack_id=%d user_stack_id=%d";

    kern_stack_id = bpf_get_stackid(ctx, &stack_traces, 0);
    user_stack_id = bpf_get_stackid(ctx, &stack_traces, 0 | BPF_F_USER_STACK);

    if kern_stack_id >= 0 && user_stack_id >=0 {
        bpf_trace_printk(fmt, sizeof(fmt), kern_stack_id, user_stack_id);
    }
}

char _license[] SEC("license") = "GPL";

Complete examples in the Linux source bpf samples: