From f44e6f40031410d6a53668d1c7e361fe4bfeec07 Mon Sep 17 00:00:00 2001 From: Florian Lehner Date: Thu, 15 Aug 2024 10:14:08 +0200 Subject: [PATCH] Off CPU profiling This is the code that backs https://github.com/open-telemetry/opentelemetry-ebpf-profiler/pull/144. It can be reused to add features like requested in https://github.com/open-telemetry/opentelemetry-ebpf-profiler/issues/33 and therefore can be an alternative to https://github.com/open-telemetry/opentelemetry-ebpf-profiler/pull/192. The idea that enables off CPU profiling is, that perf event and kprobe eBPF programs are quite similar and can be converted. This allows, with the dynamic rewrite of tail call maps, the reuse of existing eBPF programs and concepts. This proposal adds the new flag '-off-cpu-threshold' that enables off CPU profiling and attaches the two additional hooks, as discussed in Option B in https://github.com/open-telemetry/opentelemetry-ebpf-profiler/pull/144. Outstanding work: - [ ] Handle off CPU traces in the reporter package - [ ] Handle off CPU traces in the user space side Signed-off-by: Florian Lehner --- cli_flags.go | 9 + internal/controller/config.go | 1 + internal/controller/controller.go | 7 + support/ebpf/bpfdefs.h | 2 + support/ebpf/extmaps.h | 4 +- support/ebpf/integration_test.ebpf.c | 8 +- support/ebpf/interpreter_dispatcher.ebpf.c | 4 +- support/ebpf/native_stack_trace.ebpf.c | 213 +----------- support/ebpf/off_cpu.ebpf.c | 86 +++++ support/ebpf/tracemgmt.h | 212 +++++++++++- support/ebpf/tracer.ebpf.release.amd64 | Bin 298296 -> 305080 bytes support/ebpf/types.h | 22 ++ support/types.go | 8 + tracer/ebpf_integration_test.go | 2 +- tracer/systemconfig.go | 3 +- tracer/tracer.go | 359 ++++++++++++++------- 16 files changed, 609 insertions(+), 331 deletions(-) create mode 100644 support/ebpf/off_cpu.ebpf.c diff --git a/cli_flags.go b/cli_flags.go index ac1ca806..724f1890 100644 --- a/cli_flags.go +++ b/cli_flags.go @@ -24,6 +24,7 @@ const ( defaultProbabilisticThreshold = tracer.ProbabilisticThresholdMax defaultProbabilisticInterval = 1 * time.Minute defaultArgSendErrorFrames = false + defaultOffCPUThreshold = tracer.OffCPUThresholdMax // This is the X in 2^(n + x) where n is the default hardcoded map size value defaultArgMapScaleFactor = 0 @@ -61,6 +62,11 @@ var ( "If zero, monotonic-realtime clock sync will be performed once, " + "on agent startup, but not periodically." sendErrorFramesHelp = "Send error frames (devfiler only, breaks Kibana)" + offCPUThresholdHelp = fmt.Sprintf("If set to a value between 1 and %d will enable "+ + "off cpu profiling: Every time an off-cpu entry point is hit, a random number between "+ + "0 and %d is chosen. If the given threshold is greater than this random number, the off "+ + "cpu trace is collected and reported.", + tracer.OffCPUThresholdMax-1, tracer.OffCPUThresholdMax-1) ) // Package-scope variable, so that conditionally compiled other components can refer @@ -114,6 +120,9 @@ func parseArgs() (*controller.Config, error) { fs.BoolVar(&args.VerboseMode, "verbose", false, verboseModeHelp) fs.BoolVar(&args.Version, "version", false, versionHelp) + fs.UintVar(&args.OffCPUThreshold, "off-cpu-threshold", + defaultOffCPUThreshold, offCPUThresholdHelp) + fs.Usage = func() { fs.PrintDefaults() } diff --git a/internal/controller/config.go b/internal/controller/config.go index 16daddc6..6885dc4a 100644 --- a/internal/controller/config.go +++ b/internal/controller/config.go @@ -30,6 +30,7 @@ type Config struct { Tracers string VerboseMode bool Version bool + OffCPUThreshold uint Reporter reporter.Reporter diff --git a/internal/controller/controller.go b/internal/controller/controller.go index 6f9d6d4e..089d7838 100644 --- a/internal/controller/controller.go +++ b/internal/controller/controller.go @@ -133,6 +133,13 @@ func (c *Controller) Start(ctx context.Context) error { } log.Info("Attached tracer program") + if c.config.OffCPUThreshold < tracer.OffCPUThresholdMax { + if err := trc.StartOffCPUProfiling(); err != nil { + return fmt.Errorf("failed to start off-cpu profiling: %v", err) + } + log.Printf("Enabled off-cpu profiling") + } + if c.config.ProbabilisticThreshold < tracer.ProbabilisticThresholdMax { trc.StartProbabilisticProfiling(ctx) log.Printf("Enabled probabilistic profiling") diff --git a/support/ebpf/bpfdefs.h b/support/ebpf/bpfdefs.h index 7171b3c2..1271f845 100644 --- a/support/ebpf/bpfdefs.h +++ b/support/ebpf/bpfdefs.h @@ -83,6 +83,8 @@ static int (*bpf_perf_event_output)(void *ctx, void *map, unsigned long long fla (void *)BPF_FUNC_perf_event_output; static int (*bpf_get_stackid)(void *ctx, void *map, u64 flags) = (void *)BPF_FUNC_get_stackid; +static unsigned long long (*bpf_get_prandom_u32)(void) = + (void *) BPF_FUNC_get_prandom_u32; __attribute__ ((format (printf, 1, 3))) static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) = diff --git a/support/ebpf/extmaps.h b/support/ebpf/extmaps.h index 76a83f57..7b2926c1 100644 --- a/support/ebpf/extmaps.h +++ b/support/ebpf/extmaps.h @@ -6,8 +6,9 @@ #include "bpf_map.h" // References to map definitions in *.ebpf.c. -extern bpf_map_def progs; +extern bpf_map_def perf_progs; extern bpf_map_def per_cpu_records; +extern bpf_map_def kernel_stackmap; extern bpf_map_def pid_page_to_mapping_info; extern bpf_map_def metrics; extern bpf_map_def report_events; @@ -39,7 +40,6 @@ extern bpf_map_def exe_id_to_19_stack_deltas; extern bpf_map_def exe_id_to_20_stack_deltas; extern bpf_map_def exe_id_to_21_stack_deltas; extern bpf_map_def hotspot_procs; -extern bpf_map_def kernel_stackmap; extern bpf_map_def dotnet_procs; extern bpf_map_def perl_procs; extern bpf_map_def php_procs; diff --git a/support/ebpf/integration_test.ebpf.c b/support/ebpf/integration_test.ebpf.c index 510e72c6..dd01a060 100644 --- a/support/ebpf/integration_test.ebpf.c +++ b/support/ebpf/integration_test.ebpf.c @@ -80,10 +80,10 @@ void send_sample_traces(void *ctx, u64 pid, s32 kstack) { send_trace(ctx, trace); } -// tracepoint__sched_switch fetches the current kernel stack ID from kernel_stackmap and -// communicates it to userspace via kernel_stack_id map. -SEC("tracepoint/sched/sched_switch") -int tracepoint__sched_switch(void *ctx) { +// tracepoint_integration__sched_switch fetches the current kernel stack ID from +// kernel_stackmap and communicates it to userspace via kernel_stack_id map. +SEC("tracepoint/integration/sched_switch") +int tracepoint_integration__sched_switch(void *ctx) { u64 id = bpf_get_current_pid_tgid(); u64 pid = id >> 32; diff --git a/support/ebpf/interpreter_dispatcher.ebpf.c b/support/ebpf/interpreter_dispatcher.ebpf.c index d4788f9b..54d09664 100644 --- a/support/ebpf/interpreter_dispatcher.ebpf.c +++ b/support/ebpf/interpreter_dispatcher.ebpf.c @@ -25,8 +25,8 @@ bpf_map_def SEC("maps") metrics = { .max_entries = metricID_Max, }; -// progs maps from a program ID to an eBPF program -bpf_map_def SEC("maps") progs = { +// perf_progs maps from a program ID to a perf eBPF program +bpf_map_def SEC("maps") perf_progs = { .type = BPF_MAP_TYPE_PROG_ARRAY, .key_size = sizeof(u32), .value_size = sizeof(u32), diff --git a/support/ebpf/native_stack_trace.ebpf.c b/support/ebpf/native_stack_trace.ebpf.c index d9c56f3b..f4727d6f 100644 --- a/support/ebpf/native_stack_trace.ebpf.c +++ b/support/ebpf/native_stack_trace.ebpf.c @@ -4,14 +4,6 @@ #include "tracemgmt.h" #include "stackdeltatypes.h" -#ifndef __USER32_CS - // defined in arch/x86/include/asm/segment.h - #define GDT_ENTRY_DEFAULT_USER32_CS 4 - #define GDT_ENTRY_DEFAULT_USER_DS 5 - #define __USER32_CS (GDT_ENTRY_DEFAULT_USER32_CS*8 + 3) - #define __USER_DS (GDT_ENTRY_DEFAULT_USER_DS*8 + 3) -#endif - // Macro to create a map named exe_id_to_X_stack_deltas that is a nested maps with a fileID for the // outer map and an array as inner map that holds up to 2^X stack delta entries for the given fileID. #define STACK_DELTA_BUCKET(X) \ @@ -602,151 +594,6 @@ static ErrorCode unwind_one_frame(u64 pid, u32 frame_idx, struct UnwindState *st #error unsupported architecture #endif -// Initialize state from pt_regs -static inline ErrorCode copy_state_regs(UnwindState *state, - struct pt_regs *regs, - bool interrupted_kernelmode) -{ -#if defined(__x86_64__) - // Check if the process is running in 32-bit mode on the x86_64 system. - // This check follows the Linux kernel implementation of user_64bit_mode() in - // arch/x86/include/asm/ptrace.h. - if (regs->cs == __USER32_CS) { - return ERR_NATIVE_X64_32BIT_COMPAT_MODE; - } - state->pc = regs->ip; - state->sp = regs->sp; - state->fp = regs->bp; - state->rax = regs->ax; - state->r9 = regs->r9; - state->r11 = regs->r11; - state->r13 = regs->r13; - state->r15 = regs->r15; - - // Treat syscalls as return addresses, but not IRQ handling, page faults, etc.. - // https://github.com/torvalds/linux/blob/2ef5971ff3/arch/x86/include/asm/syscall.h#L31-L39 - // https://github.com/torvalds/linux/blob/2ef5971ff3/arch/x86/entry/entry_64.S#L847 - state->return_address = interrupted_kernelmode && regs->orig_ax != -1; -#elif defined(__aarch64__) - // For backwards compatibility aarch64 can run 32-bit code. - // Check if the process is running in this 32-bit compat mod. - if (regs->pstate & PSR_MODE32_BIT) { - return ERR_NATIVE_AARCH64_32BIT_COMPAT_MODE; - } - state->pc = normalize_pac_ptr(regs->pc); - state->sp = regs->sp; - state->fp = regs->regs[29]; - state->lr = normalize_pac_ptr(regs->regs[30]); - state->r22 = regs->regs[22]; - - // Treat syscalls as return addresses, but not IRQ handling, page faults, etc.. - // https://github.com/torvalds/linux/blob/2ef5971ff3/arch/arm64/include/asm/ptrace.h#L118 - // https://github.com/torvalds/linux/blob/2ef5971ff3/arch/arm64/include/asm/ptrace.h#L206-L209 - state->return_address = interrupted_kernelmode && regs->syscallno != -1; -#endif - - return ERR_OK; -} - -#ifndef TESTING_COREDUMP - -// Read the task's entry stack pt_regs. This has identical functionality -// to bpf_task_pt_regs which is emulated to support older kernels. -// Once kernel requirement is increased to 5.15 this can be replaced with -// the bpf_task_pt_regs() helper. -static inline -long get_task_pt_regs(struct task_struct *task, SystemConfig* syscfg) { - u64 stack_ptr = (u64)task + syscfg->task_stack_offset; - long stack_base; - if (bpf_probe_read_kernel(&stack_base, sizeof(stack_base), (void*) stack_ptr)) { - return 0; - } - return stack_base + syscfg->stack_ptregs_offset; -} - -// Determine whether the given pt_regs are from user-mode register context. -// This needs to detect also invalid pt_regs in case we its kernel thread stack -// without valid user mode pt_regs so is_kernel_address(pc) is not enough. -static inline -bool ptregs_is_usermode(struct pt_regs *regs) { -#if defined(__x86_64__) - // On x86_64 the user mode SS should always be __USER_DS. - if (regs->ss != __USER_DS) { - return false; - } - return true; -#elif defined(__aarch64__) - // Check if the processor state is in the EL0t what linux uses for usermode. - if ((regs->pstate & PSR_MODE_MASK) != PSR_MODE_EL0t) { - return false; - } - return true; -#else -#error add support for new architecture -#endif -} - -// Extract the usermode pt_regs for current task. Use context given pt_regs -// if it is usermode regs, or resolve it via struct task_struct. -// -// State registers are not touched (get_pristine_per_cpu_record already reset it) -// if something fails. has_usermode_regs is set to true if a user-mode register -// context was found: not every thread that we interrupt will actually have -// a user-mode context (e.g. kernel worker threads won't). -static inline ErrorCode get_usermode_regs(struct pt_regs *ctx, - UnwindState *state, - bool *has_usermode_regs) { - ErrorCode error; - - if (!ptregs_is_usermode(ctx)) { - u32 key = 0; - SystemConfig* syscfg = bpf_map_lookup_elem(&system_config, &key); - if (!syscfg) { - // Unreachable: array maps are always fully initialized. - return ERR_UNREACHABLE; - } - - // Use the current task's entry pt_regs - struct task_struct *task = (struct task_struct *) bpf_get_current_task(); - long ptregs_addr = get_task_pt_regs(task, syscfg); - - struct pt_regs regs; - if (!ptregs_addr || bpf_probe_read_kernel(®s, sizeof(regs), (void*) ptregs_addr)) { - increment_metric(metricID_UnwindNativeErrReadKernelModeRegs); - return ERR_NATIVE_READ_KERNELMODE_REGS; - } - - if (!ptregs_is_usermode(®s)) { - // No usermode registers context found. - return ERR_OK; - } - error = copy_state_regs(state, ®s, true); - } else { - // User mode code interrupted, registers are available via the ebpf context. - error = copy_state_regs(state, ctx, false); - } - if (error == ERR_OK) { - DEBUG_PRINT("Read regs: pc: %llx sp: %llx fp: %llx", state->pc, state->sp, state->fp); - *has_usermode_regs = true; - } - return error; -} - -#else // TESTING_COREDUMP - -static inline ErrorCode get_usermode_regs(struct pt_regs *ctx, - UnwindState *state, - bool *has_usermode_regs) { - // Coredumps provide always usermode pt_regs directly. - ErrorCode error = copy_state_regs(state, ctx, false); - if (error == ERR_OK) { - *has_usermode_regs = true; - } - return error; -} - -#endif - SEC("perf_event/unwind_native") int unwind_native(struct pt_regs *ctx) { PerCPURecord *record = get_per_cpu_record(); @@ -799,65 +646,11 @@ int unwind_native(struct pt_regs *ctx) { return -1; } -static inline -int collect_trace(struct pt_regs *ctx) { +SEC("perf_event/native_tracer_entry") +int native_tracer_entry(struct bpf_perf_event_data *ctx) { // Get the PID and TGID register. u64 id = bpf_get_current_pid_tgid(); u32 pid = id >> 32; u32 tid = id & 0xFFFFFFFF; - - if (pid == 0) { - return 0; - } - - u64 ktime = bpf_ktime_get_ns(); - - DEBUG_PRINT("==== do_perf_event ===="); - - // The trace is reused on each call to this function so we have to reset the - // variables used to maintain state. - DEBUG_PRINT("Resetting CPU record"); - PerCPURecord *record = get_pristine_per_cpu_record(); - if (!record) { - return -1; - } - - Trace *trace = &record->trace; - trace->pid = pid; - trace->tid = tid; - trace->ktime = ktime; - if (bpf_get_current_comm(&(trace->comm), sizeof(trace->comm)) < 0) { - increment_metric(metricID_ErrBPFCurrentComm); - } - - // Get the kernel mode stack trace first - trace->kernel_stack_id = bpf_get_stackid(ctx, &kernel_stackmap, BPF_F_REUSE_STACKID); - DEBUG_PRINT("kernel stack id = %d", trace->kernel_stack_id); - - // Recursive unwind frames - int unwinder = PROG_UNWIND_STOP; - bool has_usermode_regs = false; - ErrorCode error = get_usermode_regs(ctx, &record->state, &has_usermode_regs); - if (error || !has_usermode_regs) { - goto exit; - } - - if (!pid_information_exists(ctx, pid)) { - if (report_pid(ctx, pid, RATELIMIT_ACTION_DEFAULT)) { - increment_metric(metricID_NumProcNew); - } - return 0; - } - error = get_next_unwinder_after_native_frame(record, &unwinder); - -exit: - record->state.unwind_error = error; - tail_call(ctx, unwinder); - DEBUG_PRINT("bpf_tail call failed for %d in native_tracer_entry", unwinder); - return -1; -} - -SEC("perf_event/native_tracer_entry") -int native_tracer_entry(struct bpf_perf_event_data *ctx) { - return collect_trace((struct pt_regs*) &ctx->regs); + return collect_trace((struct pt_regs*) &ctx->regs, TRACE_SAMPLING, pid, tid, 0); } diff --git a/support/ebpf/off_cpu.ebpf.c b/support/ebpf/off_cpu.ebpf.c new file mode 100644 index 00000000..8132b148 --- /dev/null +++ b/support/ebpf/off_cpu.ebpf.c @@ -0,0 +1,86 @@ +#include "bpfdefs.h" +#include "types.h" +#include "tracemgmt.h" + +// kprobe_progs maps from a program ID to a kprobe eBPF program +bpf_map_def SEC("maps") kprobe_progs = { + .type = BPF_MAP_TYPE_PROG_ARRAY, + .key_size = sizeof(u32), + .value_size = sizeof(u32), + .max_entries = NUM_TRACER_PROGS, +}; + +// profile_off_cpu communicates scheduler tasks. +bpf_map_def SEC("maps") profile_off_cpu = { + .type = BPF_MAP_TYPE_LRU_PERCPU_HASH, + .key_size = sizeof(u64), // pid_tgid + .value_size = sizeof(u64), // time in ns + .max_entries = 256, +}; + +// tracepoint__sched_switch serves as entry point for off cpu profiling. +SEC("tracepoint/sched/sched_switch") +int tracepoint__sched_switch(void *ctx) { + u64 pid_tgid = bpf_get_current_pid_tgid(); + u32 pid = pid_tgid >> 32; + u32 tid = pid_tgid & 0xFFFFFFFF; + + if (pid == 0 || tid == 0) { + return 0; + } + + u32 key = 0; + SystemConfig* syscfg = bpf_map_lookup_elem(&system_config, &key); + if (!syscfg) { + // Unreachable: array maps are always fully initialized. + return ERR_UNREACHABLE; + } + + if (bpf_get_prandom_u32()%OFF_CPU_THRESHOLD_MAX > syscfg->off_cpu_threshold) { + return 0; + } + + u64 ts = bpf_ktime_get_ns(); + + if (bpf_map_update_elem(&profile_off_cpu, &pid_tgid, &ts, BPF_ANY)<0){ + return 0; + } + + return 0; +} + +// dummy is never loaded or called. It just makes sure kprobe_progs is referenced +// and make the compiler and linker happy. +SEC("kprobe/dummy") +int dummy(struct pt_regs *ctx) { + bpf_tail_call(ctx, &kprobe_progs,0); + return 0; +} + +// kp__finish_task_switch is triggered right after the scheduler updated +// the CPU registers. +SEC("kprobe/finish_task_switch") +int finish_task_switch(struct pt_regs *ctx) { + // Get the PID and TGID register. + u64 pid_tgid = bpf_get_current_pid_tgid(); + u32 pid = pid_tgid >> 32; + u32 tid = pid_tgid & 0xFFFFFFFF; + + if (pid == 0 || tid == 0) { + return 0; + } + + u64 ts = bpf_ktime_get_ns(); + + u64 *start_ts = bpf_map_lookup_elem(&profile_off_cpu, &pid_tgid); + if (!start_ts){ + // There is no information from the sched/sched_switch entry hook. + return 0; + } + + DEBUG_PRINT("==== finish_task_switch ===="); + + u64 diff = ts - *start_ts; + + return collect_trace(ctx, TRACE_OFF_CPU, pid, tid, diff); +} \ No newline at end of file diff --git a/support/ebpf/tracemgmt.h b/support/ebpf/tracemgmt.h index d2c58d53..e665f02e 100644 --- a/support/ebpf/tracemgmt.h +++ b/support/ebpf/tracemgmt.h @@ -423,10 +423,10 @@ int get_next_unwinder_after_interpreter(const PerCPURecord *record) { // tail_call is a wrapper around bpf_tail_call() and ensures that the number of tail calls is not // reached while unwinding the stack. static inline __attribute__((__always_inline__)) -void tail_call(void *ctx, int next) { +void tail_call(void *ctx, int next) { PerCPURecord *record = get_per_cpu_record(); if (!record) { - bpf_tail_call(ctx, &progs, PROG_UNWIND_STOP); + bpf_tail_call(ctx, &perf_progs, PROG_UNWIND_STOP); // In theory bpf_tail_call() should never return. But due to instruction reordering by the // compiler we have to place return here to bribe the verifier to accept this. return; @@ -444,7 +444,213 @@ void tail_call(void *ctx, int next) { } record->tailCalls += 1 ; - bpf_tail_call(ctx, &progs, next); + bpf_tail_call(ctx, &perf_progs, next); +} + +#ifndef __USER32_CS + // defined in arch/x86/include/asm/segment.h + #define GDT_ENTRY_DEFAULT_USER32_CS 4 + #define GDT_ENTRY_DEFAULT_USER_DS 5 + #define __USER32_CS (GDT_ENTRY_DEFAULT_USER32_CS*8 + 3) + #define __USER_DS (GDT_ENTRY_DEFAULT_USER_DS*8 + 3) +#endif + +// Initialize state from pt_regs +static inline ErrorCode copy_state_regs(UnwindState *state, + struct pt_regs *regs, + bool interrupted_kernelmode) +{ +#if defined(__x86_64__) + // Check if the process is running in 32-bit mode on the x86_64 system. + // This check follows the Linux kernel implementation of user_64bit_mode() in + // arch/x86/include/asm/ptrace.h. + if (regs->cs == __USER32_CS) { + return ERR_NATIVE_X64_32BIT_COMPAT_MODE; + } + state->pc = regs->ip; + state->sp = regs->sp; + state->fp = regs->bp; + state->rax = regs->ax; + state->r9 = regs->r9; + state->r11 = regs->r11; + state->r13 = regs->r13; + state->r15 = regs->r15; + + // Treat syscalls as return addresses, but not IRQ handling, page faults, etc.. + // https://github.com/torvalds/linux/blob/2ef5971ff3/arch/x86/include/asm/syscall.h#L31-L39 + // https://github.com/torvalds/linux/blob/2ef5971ff3/arch/x86/entry/entry_64.S#L847 + state->return_address = interrupted_kernelmode && regs->orig_ax != -1; +#elif defined(__aarch64__) + // For backwards compatibility aarch64 can run 32-bit code. + // Check if the process is running in this 32-bit compat mod. + if (regs->pstate & PSR_MODE32_BIT) { + return ERR_NATIVE_AARCH64_32BIT_COMPAT_MODE; + } + state->pc = normalize_pac_ptr(regs->pc); + state->sp = regs->sp; + state->fp = regs->regs[29]; + state->lr = normalize_pac_ptr(regs->regs[30]); + state->r22 = regs->regs[22]; + + // Treat syscalls as return addresses, but not IRQ handling, page faults, etc.. + // https://github.com/torvalds/linux/blob/2ef5971ff3/arch/arm64/include/asm/ptrace.h#L118 + // https://github.com/torvalds/linux/blob/2ef5971ff3/arch/arm64/include/asm/ptrace.h#L206-L209 + state->return_address = interrupted_kernelmode && regs->syscallno != -1; +#endif + + return ERR_OK; +} + +#ifndef TESTING_COREDUMP + +// Read the task's entry stack pt_regs. This has identical functionality +// to bpf_task_pt_regs which is emulated to support older kernels. +// Once kernel requirement is increased to 5.15 this can be replaced with +// the bpf_task_pt_regs() helper. +static inline +long get_task_pt_regs(struct task_struct *task, SystemConfig* syscfg) { + u64 stack_ptr = (u64)task + syscfg->task_stack_offset; + long stack_base; + if (bpf_probe_read_kernel(&stack_base, sizeof(stack_base), (void*) stack_ptr)) { + return 0; + } + return stack_base + syscfg->stack_ptregs_offset; +} + +// Determine whether the given pt_regs are from user-mode register context. +// This needs to detect also invalid pt_regs in case we its kernel thread stack +// without valid user mode pt_regs so is_kernel_address(pc) is not enough. +static inline +bool ptregs_is_usermode(struct pt_regs *regs) { +#if defined(__x86_64__) + // On x86_64 the user mode SS should always be __USER_DS. + if (regs->ss != __USER_DS) { + return false; + } + return true; +#elif defined(__aarch64__) + // Check if the processor state is in the EL0t what linux uses for usermode. + if ((regs->pstate & PSR_MODE_MASK) != PSR_MODE_EL0t) { + return false; + } + return true; +#else +#error add support for new architecture +#endif +} + +// Extract the usermode pt_regs for current task. Use context given pt_regs +// if it is usermode regs, or resolve it via struct task_struct. +// +// State registers are not touched (get_pristine_per_cpu_record already reset it) +// if something fails. has_usermode_regs is set to true if a user-mode register +// context was found: not every thread that we interrupt will actually have +// a user-mode context (e.g. kernel worker threads won't). +static inline ErrorCode get_usermode_regs(struct pt_regs *ctx, + UnwindState *state, + bool *has_usermode_regs) { + ErrorCode error; + + if (!ptregs_is_usermode(ctx)) { + u32 key = 0; + SystemConfig* syscfg = bpf_map_lookup_elem(&system_config, &key); + if (!syscfg) { + // Unreachable: array maps are always fully initialized. + return ERR_UNREACHABLE; + } + + // Use the current task's entry pt_regs + struct task_struct *task = (struct task_struct *) bpf_get_current_task(); + long ptregs_addr = get_task_pt_regs(task, syscfg); + + struct pt_regs regs; + if (!ptregs_addr || bpf_probe_read_kernel(®s, sizeof(regs), (void*) ptregs_addr)) { + increment_metric(metricID_UnwindNativeErrReadKernelModeRegs); + return ERR_NATIVE_READ_KERNELMODE_REGS; + } + + if (!ptregs_is_usermode(®s)) { + // No usermode registers context found. + return ERR_OK; + } + error = copy_state_regs(state, ®s, true); + } else { + // User mode code interrupted, registers are available via the ebpf context. + error = copy_state_regs(state, ctx, false); + } + if (error == ERR_OK) { + DEBUG_PRINT("Read regs: pc: %llx sp: %llx fp: %llx", state->pc, state->sp, state->fp); + *has_usermode_regs = true; + } + return error; +} + +#else // TESTING_COREDUMP + +static inline ErrorCode get_usermode_regs(struct pt_regs *ctx, + UnwindState *state, + bool *has_usermode_regs) { + // Coredumps provide always usermode pt_regs directly. + ErrorCode error = copy_state_regs(state, ctx, false); + if (error == ERR_OK) { + *has_usermode_regs = true; + } + return error; +} + +#endif // TESTING_COREDUMP + +static inline +int collect_trace(struct pt_regs *ctx, TraceOrigin origin, u32 pid, u32 tid, u64 off_cpu_time) { + if (pid == 0) { + return 0; + } + + u64 ktime = bpf_ktime_get_ns(); + + // The trace is reused on each call to this function so we have to reset the + // variables used to maintain state. + DEBUG_PRINT("Resetting CPU record"); + PerCPURecord *record = get_pristine_per_cpu_record(); + if (!record) { + return -1; + } + + Trace *trace = &record->trace; + trace->origin = origin; + trace->pid = pid; + trace->tid = tid; + trace->ktime = ktime; + trace->offtime = off_cpu_time; + if (bpf_get_current_comm(&(trace->comm), sizeof(trace->comm)) < 0) { + increment_metric(metricID_ErrBPFCurrentComm); + } + + // Get the kernel mode stack trace first + trace->kernel_stack_id = bpf_get_stackid(ctx, &kernel_stackmap, BPF_F_REUSE_STACKID); + DEBUG_PRINT("kernel stack id = %d", trace->kernel_stack_id); + + // Recursive unwind frames + int unwinder = PROG_UNWIND_STOP; + bool has_usermode_regs = false; + ErrorCode error = get_usermode_regs(ctx, &record->state, &has_usermode_regs); + if (error || !has_usermode_regs) { + goto exit; + } + + if (!pid_information_exists(ctx, pid)) { + if (report_pid(ctx, pid, RATELIMIT_ACTION_DEFAULT)) { + increment_metric(metricID_NumProcNew); + } + return 0; + } + error = get_next_unwinder_after_native_frame(record, &unwinder); + +exit: + record->state.unwind_error = error; + tail_call(ctx, unwinder); + DEBUG_PRINT("bpf_tail call failed for %d in native_tracer_entry", unwinder); + return -1; } #endif diff --git a/support/ebpf/tracer.ebpf.release.amd64 b/support/ebpf/tracer.ebpf.release.amd64 index ea530c95d134f069f365a1e17f73a1b9c3944a2e..73f744148b1a5e13235613c934a63c345d757176 100644 GIT binary patch literal 305080 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 literal 298296 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 E-(21P#sB~S diff --git a/support/ebpf/types.h b/support/ebpf/types.h index f161a284..1200599e 100644 --- a/support/ebpf/types.h +++ b/support/ebpf/types.h @@ -331,6 +331,17 @@ typedef enum TracePrograms { NUM_TRACER_PROGS, } TracePrograms; +// TraceOrigin describes the source of the trace. This enables +// origin specific handling of traces in user space. +typedef enum TraceOrigin { + TRACE_UNKNOWN, + TRACE_SAMPLING, + TRACE_OFF_CPU, +} TraceOrigin; + +// OFF_CPU_THRESHOLD_MAX defines the maximum threshold. +#define OFF_CPU_THRESHOLD_MAX 1000 + // MAX_FRAME_UNWINDS defines the maximum number of frames per // Trace we can unwind and respect the limit of eBPF instructions, // limit of tail calls and limit of stack size per eBPF program. @@ -532,6 +543,14 @@ typedef struct Trace { s32 kernel_stack_id; // The number of frames in the stack. u32 stack_len; + + // origin indicates the source of the trace. + TraceOrigin origin; + + // Time in nanosecond for off-cpu profiling, + // for how long the trace was off cpu. + u64 offtime; + // The frames of the stack trace. Frame frames[MAX_FRAME_UNWINDS]; @@ -840,6 +859,9 @@ typedef struct SystemConfig { // The offset of struct pt_regs within the kernel entry stack. u32 stack_ptregs_offset; + // User defined threshold for off-cpu profiling. + u32 off_cpu_threshold; + // Enables the temporary hack that drops pure errors frames in unwind_stop. bool drop_error_only_traces; } SystemConfig; diff --git a/support/types.go b/support/types.go index 6387e4d0..a37f38aa 100644 --- a/support/types.go +++ b/support/types.go @@ -105,3 +105,11 @@ const ( // PerfMaxStackDepth is the bpf map data array length for BPF_MAP_TYPE_STACK_TRACE traces PerfMaxStackDepth = C.PERF_MAX_STACK_DEPTH ) + +const ( + TraceOriginUnknown = C.TRACE_UNKNOWN + TraceOriginSampling = C.TRACE_SAMPLING + TraceOriginOffCPU = C.TRACE_OFF_CPU +) + +const OffCPUThresholdMax = C.OFF_CPU_THRESHOLD_MAX diff --git a/tracer/ebpf_integration_test.go b/tracer/ebpf_integration_test.go index 19e3c648..d671aca2 100644 --- a/tracer/ebpf_integration_test.go +++ b/tracer/ebpf_integration_test.go @@ -56,7 +56,7 @@ func runKernelFrameProbe(t *testing.T, tracer *Tracer) { require.NoError(t, err) defer restoreRlimit() - prog, err := cebpf.NewProgram(coll.Programs["tracepoint__sched_switch"]) + prog, err := cebpf.NewProgram(coll.Programs["tracepoint_integration__sched_switch"]) require.NoError(t, err) defer prog.Close() diff --git a/tracer/systemconfig.go b/tracer/systemconfig.go index 7fab17be..474b30d7 100644 --- a/tracer/systemconfig.go +++ b/tracer/systemconfig.go @@ -223,7 +223,7 @@ func determineStackLayout(coll *cebpf.CollectionSpec, maps map[string]*cebpf.Map func loadSystemConfig(coll *cebpf.CollectionSpec, maps map[string]*cebpf.Map, kernelSymbols *libpf.SymbolMap, includeTracers types.IncludedTracers, - filterErrorFrames bool) error { + offCPUThreshold uint32, filterErrorFrames bool) error { pacMask := pacmask.GetPACMask() if pacMask != 0 { log.Infof("Determined PAC mask to be 0x%016X", pacMask) @@ -233,6 +233,7 @@ func loadSystemConfig(coll *cebpf.CollectionSpec, maps map[string]*cebpf.Map, syscfg := C.SystemConfig{ inverse_pac_mask: ^C.u64(pacMask), drop_error_only_traces: C.bool(filterErrorFrames), + off_cpu_threshold: C.u32(offCPUThreshold), } if err := parseBTF(&syscfg); err != nil { diff --git a/tracer/tracer.go b/tracer/tracer.go index f34b81df..34ba1819 100644 --- a/tracer/tracer.go +++ b/tracer/tracer.go @@ -19,6 +19,7 @@ import ( "unsafe" cebpf "github.com/cilium/ebpf" + "github.com/cilium/ebpf/asm" "github.com/cilium/ebpf/link" "github.com/elastic/go-perf" log "github.com/sirupsen/logrus" @@ -64,6 +65,12 @@ const ( probProfilingDisable = -1 ) +const ( + // OffCpuThresholdMax defines the upper bound for the off-cpu profiling + // threshold. + OffCPUThresholdMax = support.OffCPUThresholdMax +) + // Intervals is a subset of config.IntervalsAndTimers. type Intervals interface { MonitorInterval() time.Duration @@ -153,6 +160,8 @@ type Config struct { ProbabilisticInterval time.Duration // ProbabilisticThreshold is the threshold for probabilistic profiling. ProbabilisticThreshold uint + // OffCPUThreshold is the user defined threshold for off-cpu profiling. + OffCPUThreshold uint32 } // hookPoint specifies the group and name of the hooked point in the kernel. @@ -160,6 +169,18 @@ type hookPoint struct { group, name string } +// progLoaderHelper supports the loading process of eBPF programs. +type progLoaderHelper struct { + // enable tells whether a prog shall be loaded. + enable bool + // name of the eBPF program + name string + // progID defines the ID for the eBPF program that is used as key in the tailcallMap. + progID uint32 + // noTailCallTarget indicates if this eBPF program should be added to the tailcallMap. + noTailCallTarget bool +} + // processKernelModulesMetadata computes the FileID of kernel files and reports executable metadata // for all kernel modules and the vmlinux image. func processKernelModulesMetadata(rep reporter.SymbolReporter, kernelModules *libpf.SymbolMap, @@ -267,9 +288,7 @@ func NewTracer(ctx context.Context, cfg *Config) (*Tracer, error) { } // Based on includeTracers we decide later which are loaded into the kernel. - ebpfMaps, ebpfProgs, err := initializeMapsAndPrograms(cfg.IncludeTracers, kernelSymbols, - cfg.FilterErrorFrames, cfg.MapScaleFactor, cfg.KernelVersionCheck, cfg.DebugTracer, - cfg.BPFVerifierLogLevel) + ebpfMaps, ebpfProgs, err := initializeMapsAndPrograms(kernelSymbols, cfg) if err != nil { return nil, fmt.Errorf("failed to load eBPF code: %v", err) } @@ -369,9 +388,7 @@ func buildStackDeltaTemplates(coll *cebpf.CollectionSpec) error { // initializeMapsAndPrograms loads the definitions for the eBPF maps and programs provided // by the embedded elf file and loads these into the kernel. -func initializeMapsAndPrograms(includeTracers types.IncludedTracers, - kernelSymbols *libpf.SymbolMap, filterErrorFrames bool, mapScaleFactor int, - kernelVersionCheck bool, debugTracer bool, bpfVerifierLogLevel uint32) ( +func initializeMapsAndPrograms(kernelSymbols *libpf.SymbolMap, cfg *Config) ( ebpfMaps map[string]*cebpf.Map, ebpfProgs map[string]*cebpf.Program, err error) { // Loading specifications about eBPF programs and maps from the embedded elf file // does not load them into the kernel. @@ -379,7 +396,7 @@ func initializeMapsAndPrograms(includeTracers types.IncludedTracers, // References to eBPF maps in the eBPF programs are just placeholders that need to be // replaced by the actual loaded maps later on with RewriteMaps before loading the // programs into the kernel. - coll, err := support.LoadCollectionSpec(debugTracer) + coll, err := support.LoadCollectionSpec(cfg.DebugTracer) if err != nil { return nil, nil, fmt.Errorf("failed to load specification for tracers: %v", err) } @@ -395,7 +412,7 @@ func initializeMapsAndPrograms(includeTracers types.IncludedTracers, // Load all maps into the kernel that are used later on in eBPF programs. So we can rewrite // in the next step the placesholders in the eBPF programs with the file descriptors of the // loaded maps in the kernel. - if err = loadAllMaps(coll, ebpfMaps, mapScaleFactor); err != nil { + if err = loadAllMaps(coll, ebpfMaps, cfg.MapScaleFactor); err != nil { return nil, nil, fmt.Errorf("failed to load eBPF maps: %v", err) } @@ -406,7 +423,7 @@ func initializeMapsAndPrograms(includeTracers types.IncludedTracers, return nil, nil, fmt.Errorf("failed to rewrite maps: %v", err) } - if kernelVersionCheck { + if cfg.KernelVersionCheck { var major, minor, patch uint32 major, minor, patch, err = GetCurrentKernelVersion() if err != nil { @@ -422,13 +439,68 @@ func initializeMapsAndPrograms(includeTracers types.IncludedTracers, } } - if err = loadUnwinders(coll, ebpfProgs, ebpfMaps["progs"], includeTracers, - bpfVerifierLogLevel); err != nil { - return nil, nil, fmt.Errorf("failed to load eBPF programs: %v", err) + tailCallProgs := []progLoaderHelper{ + { + progID: uint32(support.ProgUnwindStop), + name: "unwind_stop", + enable: true, + }, + { + progID: uint32(support.ProgUnwindNative), + name: "unwind_native", + enable: true, + }, + { + progID: uint32(support.ProgUnwindHotspot), + name: "unwind_hotspot", + enable: cfg.IncludeTracers.Has(types.HotspotTracer), + }, + { + progID: uint32(support.ProgUnwindPerl), + name: "unwind_perl", + enable: cfg.IncludeTracers.Has(types.PerlTracer), + }, + { + progID: uint32(support.ProgUnwindPHP), + name: "unwind_php", + enable: cfg.IncludeTracers.Has(types.PHPTracer), + }, + { + progID: uint32(support.ProgUnwindPython), + name: "unwind_python", + enable: cfg.IncludeTracers.Has(types.PythonTracer), + }, + { + progID: uint32(support.ProgUnwindRuby), + name: "unwind_ruby", + enable: cfg.IncludeTracers.Has(types.RubyTracer), + }, + { + progID: uint32(support.ProgUnwindV8), + name: "unwind_v8", + enable: cfg.IncludeTracers.Has(types.V8Tracer), + }, + { + progID: uint32(support.ProgUnwindDotnet), + name: "unwind_dotnet", + enable: cfg.IncludeTracers.Has(types.DotnetTracer), + }, + } + + if err = loadPerfUnwinders(coll, ebpfProgs, ebpfMaps["perf_progs"], tailCallProgs, + cfg.BPFVerifierLogLevel); err != nil { + return nil, nil, fmt.Errorf("failed to load perf eBPF programs: %v", err) } - if err = loadSystemConfig(coll, ebpfMaps, kernelSymbols, includeTracers, - filterErrorFrames); err != nil { + if cfg.OffCPUThreshold < OffCPUThresholdMax { + if err = loadKProbeUnwinders(coll, ebpfProgs, ebpfMaps["kprobe_progs"], tailCallProgs, + cfg.BPFVerifierLogLevel, ebpfMaps["perf_progs"].FD()); err != nil { + return nil, nil, fmt.Errorf("failed to load kprobe eBPF programs: %v", err) + } + } + + if err = loadSystemConfig(coll, ebpfMaps, kernelSymbols, cfg.IncludeTracers, + cfg.OffCPUThreshold, cfg.FilterErrorFrames); err != nil { return nil, nil, fmt.Errorf("failed to load system config: %v", err) } @@ -499,129 +571,172 @@ func loadAllMaps(coll *cebpf.CollectionSpec, ebpfMaps map[string]*cebpf.Map, return nil } -// loadUnwinders just satisfies the proof of concept and loads all eBPF programs -func loadUnwinders(coll *cebpf.CollectionSpec, ebpfProgs map[string]*cebpf.Program, - tailcallMap *cebpf.Map, includeTracers types.IncludedTracers, +// loadPerfUnwinders just satisfies the proof of concept and loads all eBPF programs +func loadPerfUnwinders(coll *cebpf.CollectionSpec, ebpfProgs map[string]*cebpf.Program, + tailcallMap *cebpf.Map, tailCallProgs []progLoaderHelper, bpfVerifierLogLevel uint32) error { - restoreRlimit, err := rlimit.MaximizeMemlock() - if err != nil { - return fmt.Errorf("failed to adjust rlimit: %v", err) + programOptions := cebpf.ProgramOptions{ + LogLevel: cebpf.LogLevel(bpfVerifierLogLevel), } - defer restoreRlimit() - type prog struct { - // enable tells whether a prog shall be loaded. - enable bool - // name of the eBPF program - name string - // progID defines the ID for the eBPF program that is used as key in the tailcallMap. - progID uint32 - // noTailCallTarget indicates if this eBPF program should be added to the tailcallMap. - noTailCallTarget bool + progs := make([]progLoaderHelper, len(tailCallProgs)+2) + copy(progs, tailCallProgs) + progs = append(progs, + progLoaderHelper{ + name: "tracepoint__sched_process_exit", + noTailCallTarget: true, + enable: true, + }, + progLoaderHelper{ + name: "native_tracer_entry", + noTailCallTarget: true, + enable: true, + }) + + for _, unwindProg := range progs { + if !unwindProg.enable { + continue + } + + progSpec, ok := coll.Programs[unwindProg.name] + if !ok { + return fmt.Errorf("program %s does not exist", unwindProg.name) + } + + if err := loadProgram(ebpfProgs, tailcallMap, unwindProg.progID, progSpec, + programOptions, unwindProg.noTailCallTarget); err != nil { + return err + } + } + + return nil +} + +// progArrayReferences returns a list of instructions which load a specified tail +// call FD. +func progArrayReferences(perfTailCallMapFD int, insns asm.Instructions) []int { + insNos := []int{} + for i := range insns { + ins := &insns[i] + if asm.OpCode(ins.OpCode.Class()) != asm.OpCode(asm.LdClass) { + continue + } + m := ins.Map() + if m == nil { + continue + } + if perfTailCallMapFD == m.FD() { + insNos = append(insNos, i) + } } + return insNos +} +// loadKProbeUnwinders reuses large parts of loadPerfUnwinders. By default all eBPF programs +// are written as perf event eBPF programs. loadKProbeUnwinders dynamically rewrites the +// specification of these programs to krpobe eBPF programs and adjusts tail call maps. +func loadKProbeUnwinders(coll *cebpf.CollectionSpec, ebpfProgs map[string]*cebpf.Program, + tailcallMap *cebpf.Map, tailCallProgs []progLoaderHelper, + bpfVerifierLogLevel uint32, perfTailCallMapFD int) error { programOptions := cebpf.ProgramOptions{ LogLevel: cebpf.LogLevel(bpfVerifierLogLevel), } - for _, unwindProg := range []prog{ - { - progID: uint32(support.ProgUnwindStop), - name: "unwind_stop", - enable: true, - }, - { - progID: uint32(support.ProgUnwindNative), - name: "unwind_native", - enable: true, - }, - { - progID: uint32(support.ProgUnwindHotspot), - name: "unwind_hotspot", - enable: includeTracers.Has(types.HotspotTracer), - }, - { - progID: uint32(support.ProgUnwindPerl), - name: "unwind_perl", - enable: includeTracers.Has(types.PerlTracer), - }, - { - progID: uint32(support.ProgUnwindPHP), - name: "unwind_php", - enable: includeTracers.Has(types.PHPTracer), - }, - { - progID: uint32(support.ProgUnwindPython), - name: "unwind_python", - enable: includeTracers.Has(types.PythonTracer), - }, - { - progID: uint32(support.ProgUnwindRuby), - name: "unwind_ruby", - enable: includeTracers.Has(types.RubyTracer), - }, - { - progID: uint32(support.ProgUnwindV8), - name: "unwind_v8", - enable: includeTracers.Has(types.V8Tracer), - }, - { - progID: uint32(support.ProgUnwindDotnet), - name: "unwind_dotnet", - enable: includeTracers.Has(types.DotnetTracer), - }, - { - name: "tracepoint__sched_process_exit", + progs := make([]progLoaderHelper, len(tailCallProgs)+2) + copy(progs, tailCallProgs) + progs = append(progs, + progLoaderHelper{ + name: "finish_task_switch", noTailCallTarget: true, enable: true, }, - { - name: "native_tracer_entry", + progLoaderHelper{ + name: "tracepoint__sched_switch", noTailCallTarget: true, enable: true, }, - } { + ) + + for _, unwindProg := range progs { if !unwindProg.enable { continue } - // Load the eBPF program into the kernel. If no error is returned, - // the eBPF program can be used/called/triggered from now on. - unwinder, err := cebpf.NewProgramWithOptions(coll.Programs[unwindProg.name], - programOptions) - if err != nil { - // These errors tend to have hundreds of lines (or more), - // so we print each line individually. - if ve, ok := err.(*cebpf.VerifierError); ok { - for _, line := range ve.Log { - log.Error(line) - } - } else { - scanner := bufio.NewScanner(strings.NewReader(err.Error())) - for scanner.Scan() { - log.Error(scanner.Text()) - } + progSpec, ok := coll.Programs[unwindProg.name] + if !ok { + return fmt.Errorf("program %s does not exist", unwindProg.name) + } + + // Replace the prog array for the tail calls. + insns := progArrayReferences(perfTailCallMapFD, progSpec.Instructions) + for _, ins := range insns { + if err := progSpec.Instructions[ins].AssociateMap(tailcallMap); err != nil { + return fmt.Errorf("failed to rewrite map ptr: %v", err) } - return fmt.Errorf("failed to load %s", unwindProg.name) } - ebpfProgs[unwindProg.name] = unwinder - fd := uint32(unwinder.FD()) - if unwindProg.noTailCallTarget { - continue + // All the tail call targets are perf event programs. To be able to tail call them + // from a kprobe, adjust their specification. + if !unwindProg.noTailCallTarget { + // Adjust program type + progSpec.Type = cebpf.Kprobe + + // Adjust program name for easier debugging + progSpec.Name = "kp_" + progSpec.Name } - if err := tailcallMap.Update(unsafe.Pointer(&unwindProg.progID), unsafe.Pointer(&fd), - cebpf.UpdateAny); err != nil { - // Every eBPF program that is loaded within loadUnwinders can be the - // destination of a tail call of another eBPF program. If we can not update - // the eBPF map that manages these destinations our unwinding will fail. - return fmt.Errorf("failed to update tailcall map: %v", err) + if err := loadProgram(ebpfProgs, tailcallMap, unwindProg.progID, progSpec, + programOptions, unwindProg.noTailCallTarget); err != nil { + return err } } return nil } +// loadProgram loads an eBPF program from progSpec and populates the related maps. +func loadProgram(ebpfProgs map[string]*cebpf.Program, tailcallMap *cebpf.Map, + progID uint32, progSpec *cebpf.ProgramSpec, programOptions cebpf.ProgramOptions, + noTailCallTarget bool) error { + restoreRlimit, err := rlimit.MaximizeMemlock() + if err != nil { + return fmt.Errorf("failed to adjust rlimit: %v", err) + } + defer restoreRlimit() + + // Load the eBPF program into the kernel. If no error is returned, + // the eBPF program can be used/called/triggered from now on. + unwinder, err := cebpf.NewProgramWithOptions(progSpec, programOptions) + if err != nil { + // These errors tend to have hundreds of lines (or more), + // so we print each line individually. + if ve, ok := err.(*cebpf.VerifierError); ok { + for _, line := range ve.Log { + log.Error(line) + } + } else { + scanner := bufio.NewScanner(strings.NewReader(err.Error())) + for scanner.Scan() { + log.Error(scanner.Text()) + } + } + return fmt.Errorf("failed to load %s", progSpec.Name) + } + ebpfProgs[progSpec.Name] = unwinder + + if noTailCallTarget { + return nil + } + fd := uint32(unwinder.FD()) + if err := tailcallMap.Update(unsafe.Pointer(&progID), unsafe.Pointer(&fd), + cebpf.UpdateAny); err != nil { + // Every eBPF program that is loaded within loadUnwinders can be the + // destination of a tail call of another eBPF program. If we can not update + // the eBPF map that manages these destinations our unwinding will fail. + return fmt.Errorf("failed to update tailcall map: %v", err) + } + return nil +} + // insertKernelFrames fetches the kernel stack frames for a particular kstackID and populates // the trace with these kernel frames. It also allocates the memory for the frames of the trace. // It returns the number of kernel frames for kstackID or an error. @@ -1154,6 +1269,34 @@ func (t *Tracer) StartProbabilisticProfiling(ctx context.Context) { }) } +// StartOffCPUProfiling starts off-cpu profiling by attaching the programs to the hooks. +func (t *Tracer) StartOffCPUProfiling() error { + // Attach the second hook for off-cpu profiling first. + kprobeProg, ok := t.ebpfProgs["finish_task_switch"] + if !ok { + return errors.New("off-cpu program finish_task_switch is not available") + } + + kprobeLink, err := link.Kprobe("finish_task_switch.isra.0", kprobeProg, nil) + if err != nil { + return err + } + t.hooks[hookPoint{group: "kprobe", name: "finish_task_switch"}] = kprobeLink + + // Attach the first hook that enables off-cpu profiling. + tpProg, ok := t.ebpfProgs["tracepoint__sched_switch"] + if !ok { + return errors.New("tracepoint__sched_switch is not available") + } + tpLink, err := link.Tracepoint("sched", "sched_switch", tpProg, nil) + if err != nil { + return nil + } + t.hooks[hookPoint{group: "sched", name: "sched_switch"}] = tpLink + + return nil +} + // TraceProcessor gets the trace processor. func (t *Tracer) TraceProcessor() tracehandler.TraceProcessor { return t.processManager