Skip to content
Merged
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
9 changes: 3 additions & 6 deletions support/ebpf/beam_tracer.ebpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@ unwind_one_beam_frame(PerCPURecord *record, BEAMProcInfo *info, BEAMRangesSearch

BEAMRangeEntry current_range = ranges->mid;

UNROLL for (int i = 0; i < BEAM_CODE_HEADER_SEARCH_ITERATIONS; i++)
{
for (int i = 0; i < BEAM_CODE_HEADER_SEARCH_ITERATIONS; i++) {
if (pc < current_range.start) {
high = current;
} else if (pc >= current_range.end) {
Expand Down Expand Up @@ -104,8 +103,7 @@ unwind_one_beam_frame(PerCPURecord *record, BEAMProcInfo *info, BEAMRangesSearch
return ERR_BEAM_FRAME_POINTER_INVALID;
}
} else {
UNROLL for (int i = 0; i < BEAM_STACK_FRAME_SCAN_ITERATIONS; i++)
{
for (int i = 0; i < BEAM_STACK_FRAME_SCAN_ITERATIONS; i++) {
// Native stack is not supported on ARM due to 16-byte stack alignment hassle
// r20 is used to store the stack pointer for JIT code to allow 8-bit alignment.
#if defined(__aarch64__)
Expand Down Expand Up @@ -216,8 +214,7 @@ static EBPF_INLINE int unwind_beam(struct pt_regs *ctx)

DEBUG_PRINT("beam: valid addresses 0x%llx - 0x%llx", ranges.first.start, ranges.last.end);

UNROLL for (int i = 0; i < BEAM_FRAMES_PER_PROGRAM; i++)
{
for (int i = 0; i < BEAM_FRAMES_PER_PROGRAM; i++) {
if (record->state.pc == info->beam_normal_exit) {
unwinder = PROG_UNWIND_STOP;
break;
Expand Down
12 changes: 0 additions & 12 deletions support/ebpf/bpfdefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,6 @@ extern u32 with_debug_output;
#define printt(fmt, ...) bpf_log(fmt, ##__VA_ARGS__)
#define DEBUG_PRINT(fmt, ...) bpf_log(fmt, ##__VA_ARGS__)

// Macro for loop unrolling. Expands to nothing for TESTING_COREDUMP.
#define UNROLL

// BPF helpers. Mostly stubs to dispatch the call to Go code with the context ID.
int bpf_tail_call(void *ctx, void *map, int index);
unsigned long long bpf_ktime_get_ns(void);
Expand Down Expand Up @@ -175,15 +172,6 @@ static long (*bpf_probe_read_kernel)(void *dst, int size, const void *unsafe_ptr
__attribute__((section(name), used)) _Pragma("GCC diagnostic pop")
#define EBPF_INLINE __attribute__((__always_inline__))

#if defined(__clang__)
// Macro for loop unrolling. Expands to the appropriate pragma for clang.
// Unrolls up to 256 loop iterations.
#define UNROLL _Pragma("unroll 256")
#else
// Macro for loop unrolling. Expands to nothing for gcc.
#define UNROLL
#endif

#endif // !TESTING_COREDUMP

#define MIN(a, b) (((a) < (b)) ? (a) : (b))
Expand Down
12 changes: 4 additions & 8 deletions support/ebpf/dotnet_tracer.ebpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,7 @@ static EBPF_INLINE ErrorCode dotnet_find_code_start(PerCPURecord *record, u64 pc
// the loop iterations is number of u64 elements minus two:
// - the last element special handled earlier
// - the second last element which is preloaded immediately above
UNROLL for (int i = 0; i < map_elements / 2 - 2; i++)
{
for (int i = 0; i < map_elements / 2 - 2; i++) {
if (val64 != 0) {
break;
}
Expand Down Expand Up @@ -151,8 +150,7 @@ static EBPF_INLINE ErrorCode dotnet_find_code_start(PerCPURecord *record, u64 pc
}

// Decode the code start info from the entry
UNROLL for (int i = 0; i < DOTNET_CODE_NIBBLES_PER_ENTRY; i++)
{
for (int i = 0; i < DOTNET_CODE_NIBBLES_PER_ENTRY; i++) {
u8 nybble = val & 0xf;
if (nybble != 0) {
*code_start = pc_base + pc_delta + (nybble - 1) * DOTNET_CODE_ALIGN;
Expand Down Expand Up @@ -267,8 +265,7 @@ static EBPF_INLINE ErrorCode dotnet10_find_code_start(PerCPURecord *record, u64

// #5.4 or contains a nibble map
decode_nibble_map:
UNROLL for (int i = 0; i < DOTNET10_NIBBLES_PER_DWORD - 1; i++)
{
for (int i = 0; i < DOTNET10_NIBBLES_PER_DWORD - 1; i++) {
if (val & DOTNET10_NIBBLE_MASK) {
break;
}
Expand Down Expand Up @@ -444,8 +441,7 @@ static EBPF_INLINE int unwind_dotnet_core(
record->ratelimitAction = RATELIMIT_ACTION_FAST;
increment_metric(metricID_UnwindDotnetAttempts);

UNROLL for (int i = 0; i < frames_per_program; i++)
{
for (int i = 0; i < frames_per_program; i++) {
unwinder = PROG_UNWIND_STOP;

error = unwind_one_dotnet_frame(record, find_code_start);
Expand Down
12 changes: 4 additions & 8 deletions support/ebpf/hotspot_tracer.ebpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,7 @@ static EBPF_INLINE u64 hotspot_find_codeblob(const UnwindState *state, const Hot
// Segment map start is put in to the PidPageMapping's file_id.
segmap_start = (state->text_section_id >> HS_TSID_SEG_MAP_BIT) & HS_TSID_SEG_MAP_MASK;

UNROLL for (int i = 0; i < HOTSPOT_SEGMAP_ITERATIONS; i++)
{
for (int i = 0; i < HOTSPOT_SEGMAP_ITERATIONS; i++) {
if (bpf_probe_read_user(&tag, sizeof(tag), (void *)(segmap_start + segment))) {
return 0;
}
Expand Down Expand Up @@ -436,8 +435,7 @@ static EBPF_INLINE bool hotspot_handle_epilogue(
// Is 'ret' instruction *possible* in the next 'code' bytes?
// NOTE: This can find false positives because x86 is variable length
// instruction set.
UNROLL for (int i = CODE_CUR + 1; i < sizeof(code); i++)
{
for (int i = CODE_CUR + 1; i < sizeof(code); i++) {
if (code[i] == 0xc3) {
goto found_ret;
}
Expand Down Expand Up @@ -535,8 +533,7 @@ hotspot_handle_epilogue(const CodeBlobInfo *cbi, HotspotUnwindInfo *ui, HotspotU
return false;
}

UNROLL for (; find_offset < EPI_LOOKBACK - 1; ++find_offset)
{
for (; find_offset < EPI_LOOKBACK - 1; ++find_offset) {
if (*(u64 *)&window[find_offset] == needle) {
goto pattern_found;
}
Expand Down Expand Up @@ -941,8 +938,7 @@ static EBPF_INLINE int unwind_hotspot(struct pt_regs *ctx)
goto exit;
}

UNROLL for (int i = 0; i < HOTSPOT_FRAMES_PER_PROGRAM; i++)
{
for (int i = 0; i < HOTSPOT_FRAMES_PER_PROGRAM; i++) {
unwinder = PROG_UNWIND_STOP;
error = hotspot_unwind_one_frame(record, ji, i == 0);
if (error) {
Expand Down
6 changes: 2 additions & 4 deletions support/ebpf/native_stack_trace.ebpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,7 @@ static EBPF_INLINE ErrorCode get_stack_delta(UnwindState *state, int *addrDiff,
// Do the binary search, up to 16 iterations. Deltas are paged to 64kB pages.
// They can contain at most 64kB deltas even if everything is single byte opcodes.
int i;
UNROLL for (i = 0; i < 16; i++)
{
for (i = 0; i < 16; i++) {
if (!bsearch_step(inner_map, &lo, &hi, page_offset)) {
break;
}
Expand Down Expand Up @@ -558,8 +557,7 @@ static EBPF_INLINE int unwind_native(struct pt_regs *ctx)
Trace *trace = &record->trace;
int unwinder;
ErrorCode error;
UNROLL for (int i = 0; i < NATIVE_FRAMES_PER_PROGRAM; i++)
{
for (int i = 0; i < NATIVE_FRAMES_PER_PROGRAM; i++) {
unwinder = PROG_UNWIND_STOP;

// Unwind native code
Expand Down
3 changes: 1 addition & 2 deletions support/ebpf/perl_tracer.ebpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -298,8 +298,7 @@ static EBPF_INLINE int walk_perl_stack(PerCPURecord *record, const PerlProcInfo

int unwinder = PROG_UNWIND_PERL;
const void *cxbase = record->perlUnwindState.cxbase;
UNROLL for (u32 i = 0; i < PERL_FRAMES_PER_PROGRAM; ++i)
{
for (u32 i = 0; i < PERL_FRAMES_PER_PROGRAM; ++i) {
// Test first the stack 'cxcur' validity. Some stacks can have 'cxix=-1'
// when they are being constructed or ran.
if (record->perlUnwindState.cxcur < cxbase) {
Expand Down
3 changes: 1 addition & 2 deletions support/ebpf/php_tracer.ebpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,7 @@ static EBPF_INLINE int walk_php_stack(PerCPURecord *record, PHPProcInfo *phpinfo

int unwinder = PROG_UNWIND_PHP;
u32 type_info = 0;
UNROLL for (u32 i = 0; i < FRAMES_PER_WALK_PHP_STACK; ++i)
{
for (u32 i = 0; i < FRAMES_PER_WALK_PHP_STACK; ++i) {
int metric = process_php_frame(record, phpinfo, is_jitted, execute_data, &type_info);
if (metric >= 0) {
increment_metric(metric);
Expand Down
3 changes: 1 addition & 2 deletions support/ebpf/python_tracer.ebpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,7 @@ walk_python_stack(PerCPURecord *record, const PyProcInfo *pyinfo, int *unwinder)
ErrorCode error = ERR_OK;
*unwinder = PROG_UNWIND_STOP;

UNROLL for (u32 i = 0; i < FRAMES_PER_WALK_PYTHON_STACK; ++i)
{
for (u32 i = 0; i < FRAMES_PER_WALK_PYTHON_STACK; ++i) {
bool continue_with_next;
error = process_python_frame(record, pyinfo, &py_frame, &continue_with_next);
if (error) {
Expand Down
6 changes: 2 additions & 4 deletions support/ebpf/ruby_tracer.ebpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,7 @@ static EBPF_INLINE ErrorCode read_ruby_frame(
// rb_vm_frame_method_entry to check the frame for a callable method entry, CME
// If it cannot find a local method entry within MAX_EP_CHECKS, it will error
// https://github.com/ruby/ruby/blob/v3_4_7/vm_insnhelper.c#L769
UNROLL for (ep_check = 0; ep_check < MAX_EP_CHECKS; ++ep_check)
{
for (ep_check = 0; ep_check < MAX_EP_CHECKS; ++ep_check) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think these should be fine, especially considering the integration tests pass. The delta in instruction counts for ruby is phenomenal (and kind of funny haha)

// This code emulates ruby's check_method_entry to traverse the environment
// until it finds a method entry. Since the function calls itself, the code
// is a bit out of order to try and optimize running as few instructions as
Expand Down Expand Up @@ -447,8 +446,7 @@ static EBPF_INLINE ErrorCode walk_ruby_stack(
record->rubyUnwindState.cfunc_saved_frame = 0;
}

UNROLL for (u32 i = 0; i < FRAMES_PER_WALK_RUBY_STACK; ++i)
{
for (u32 i = 0; i < FRAMES_PER_WALK_RUBY_STACK; ++i) {
error = read_ruby_frame(record, rubyinfo, stack_ptr, next_unwinder);
if (error != ERR_OK)
return error;
Expand Down
Binary file modified support/ebpf/tracer.ebpf.amd64
Binary file not shown.
Binary file modified support/ebpf/tracer.ebpf.arm64
Binary file not shown.
6 changes: 2 additions & 4 deletions support/ebpf/v8_tracer.ebpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,7 @@ static EBPF_INLINE ErrorCode unwind_one_v8_frame(PerCPURecord *record, V8ProcInf
}

int i;
UNROLL for (i = sizeof(stk) / sizeof(stk[0]) - 1; i >= 0; i--)
{
for (i = sizeof(stk) / sizeof(stk[0]) - 1; i >= 0; i--) {
if (stk[i] >= code_start && stk[i] < code_end) {
break;
}
Expand Down Expand Up @@ -331,8 +330,7 @@ static EBPF_INLINE int unwind_v8(struct pt_regs *ctx)

increment_metric(metricID_UnwindV8Attempts);

UNROLL for (int i = 0; i < V8_FRAMES_PER_PROGRAM; i++)
{
for (int i = 0; i < V8_FRAMES_PER_PROGRAM; i++) {
unwinder = PROG_UNWIND_STOP;

error = unwind_one_v8_frame(record, vi, i == 0);
Expand Down