Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions internal/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import (

const MiB = 1 << 20

const MaxTailCalls = 29

// Controller is an instance that runs, manages and stops the agent.
type Controller struct {
config *Config
Expand Down Expand Up @@ -85,6 +87,7 @@ func (c *Controller) Start(ctx context.Context) error {
ProbabilisticInterval: c.config.ProbabilisticInterval,
ProbabilisticThreshold: c.config.ProbabilisticThreshold,
OffCPUThreshold: uint32(c.config.OffCPUThreshold),
MaxTailCalls: MaxTailCalls,
})
if err != nil {
return fmt.Errorf("failed to load eBPF tracer: %w", err)
Expand Down
12 changes: 8 additions & 4 deletions support/ebpf/tracemgmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ static inline PerCPURecord *get_per_cpu_record(void)
static inline PerCPURecord *get_pristine_per_cpu_record()
{
PerCPURecord *record = get_per_cpu_record();
int key0 = 0;
SystemConfig *syscfg = bpf_map_lookup_elem(&system_config, &key0);
if (!syscfg)
return NULL;
if (!record)
return record;

Expand Down Expand Up @@ -235,7 +239,7 @@ static inline PerCPURecord *get_pristine_per_cpu_record()
record->luajitUnwindState.cframe = 0;
record->luajitUnwindState.is_jit = false;
record->unwindersDone = 0;
record->tailCalls = 0;
record->tailCallsRemaining = syscfg->max_tail_calls;
record->ratelimitAction = RATELIMIT_ACTION_DEFAULT;
record->customLabelsState.go_m_ptr = NULL;

Expand Down Expand Up @@ -516,8 +520,8 @@ static inline __attribute__((__always_inline__)) void tail_call(void *ctx, int n
return;
}

if (record->tailCalls >= 29) {
// The maximum tail call count we need to support on older kernels is 32. At this point
if (!record->tailCallsRemaining) {
// At this point
// there is a chance that continuing unwinding the stack would further increase the number of
// tail calls. As a result we might lose the unwound stack as no further tail calls are left
// to report it to user space. To make sure we do not run into this issue we stop unwinding
Expand All @@ -526,7 +530,7 @@ static inline __attribute__((__always_inline__)) void tail_call(void *ctx, int n
record->state.unwind_error = ERR_MAX_TAIL_CALLS;
increment_metric(metricID_MaxTailCalls);
}
record->tailCalls += 1;
--record->tailCallsRemaining;

bpf_tail_call(ctx, &perf_progs, next);
}
Expand Down
Binary file modified support/ebpf/tracer.ebpf.debug.amd64
Binary file not shown.
Binary file modified support/ebpf/tracer.ebpf.debug.arm64
Binary file not shown.
Binary file modified support/ebpf/tracer.ebpf.release.amd64
Binary file not shown.
Binary file modified support/ebpf/tracer.ebpf.release.arm64
Binary file not shown.
7 changes: 5 additions & 2 deletions support/ebpf/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ typedef enum TraceOrigin {
// 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.
#define MAX_FRAME_UNWINDS 128
#define MAX_FRAME_UNWINDS 256

// MAX_NON_ERROR_FRAME_UNWINDS defines the maximum number of frames
// to be pushed by unwinders while still leaving space for an error frame.
Expand Down Expand Up @@ -886,7 +886,7 @@ typedef struct PerCPURecord {
u32 unwindersDone;

// tailCalls tracks the number of calls to bpf_tail_call().
u8 tailCalls;
u8 tailCallsRemaining;

// ratelimitAction determines the PID event rate limiting mode
u8 ratelimitAction;
Expand Down Expand Up @@ -1051,6 +1051,9 @@ typedef struct SystemConfig {

// Enables the temporary hack that drops pure errors frames in unwind_stop.
bool drop_error_only_traces;

// Maximum number of eBPF tail calls before giving up.
u8 max_tail_calls;
} SystemConfig;

// Avoid including all of arch/arm64/include/uapi/asm/ptrace.h by copying the
Expand Down
2 changes: 1 addition & 1 deletion support/types.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion tracer/systemconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,8 @@ 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,
offCPUThreshold uint32, filterErrorFrames bool) error {
offCPUThreshold uint32, filterErrorFrames bool,
maxTailCalls uint8) error {
pacMask := pacmask.GetPACMask()
if pacMask != 0 {
log.Infof("Determined PAC mask to be 0x%016X", pacMask)
Expand All @@ -238,6 +239,7 @@ func loadSystemConfig(coll *cebpf.CollectionSpec, maps map[string]*cebpf.Map,
inverse_pac_mask: ^C.u64(pacMask),
drop_error_only_traces: C.bool(filterErrorFrames),
off_cpu_threshold: C.u32(offCPUThreshold),
max_tail_calls: C.u8(maxTailCalls),
}

if err := parseBTF(&syscfg); err != nil {
Expand Down
4 changes: 3 additions & 1 deletion tracer/tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ type Config struct {
ProbabilisticThreshold uint
// OffCPUThreshold is the user defined threshold for off-cpu profiling.
OffCPUThreshold uint32
// MaxTailCalls is the number of tail calls the eBPF is allowed to make before giving up.
MaxTailCalls uint8
}

// hookPoint specifies the group and name of the hooked point in the kernel.
Expand Down Expand Up @@ -511,7 +513,7 @@ func initializeMapsAndPrograms(kernelSymbols *libpf.SymbolMap, cfg *Config) (
}

if err = loadSystemConfig(coll, ebpfMaps, kernelSymbols, cfg.IncludeTracers,
cfg.OffCPUThreshold, cfg.FilterErrorFrames); err != nil {
cfg.OffCPUThreshold, cfg.FilterErrorFrames, cfg.MaxTailCalls); err != nil {
return nil, nil, fmt.Errorf("failed to load system config: %v", err)
}

Expand Down