Skip to content

Commit 3640915

Browse files
committed
Move base JIT comments, in_jit extraction, and LPM comment from PR #36
- Add 'Register LPM prefixes' comment to SynchronizeMappings loop - Extract in_jit bool variable from inline if condition for clarity - Improve JIT detection comments (read_ruby_frame and walk_ruby_stack) - Fix whitespace: add blank line after FRAMES_PER_WALK_RUBY_STACK define, normalize MAX_EP_CHECKS spacing - Rebuild BPF blobs
1 parent 1473882 commit 3640915

File tree

4 files changed

+19
-17
lines changed

4 files changed

+19
-17
lines changed

interpreter/ruby/ruby.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1336,6 +1336,7 @@ func (r *rubyInstance) SynchronizeMappings(ebpf interpreter.EbpfHandler,
13361336

13371337
log.Debugf("Synchronizing ruby mappings")
13381338

1339+
// Register LPM prefixes for executable anonymous mappings.
13391340
for idx := range mappings {
13401341
m := &mappings[idx]
13411342
if !m.IsExecutable() || !m.IsAnonymous() {

support/ebpf/ruby_tracer.ebpf.c

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ struct ruby_procs_t {
1919
// option is to adjust this number downwards.
2020
// NOTE: the maximum size stack is FRAMES_PER_WALK_RUBY_STACK * calls to tail_call().
2121
#define FRAMES_PER_WALK_RUBY_STACK 32
22+
2223
// When resolving a CME, we need to traverse environment pointers until we
2324
// find IMEMO_MENT. Since we can't do a while loop, we have to bound this
2425
// the max encountered in experimentation on a production rails app is 6.
@@ -29,7 +30,7 @@ struct ruby_procs_t {
2930
// This increases insn for the kernel verifier: all code in the ep check "loop"
3031
// is M*N for instruction checks, so be extra sensitive about additions there.
3132
// If we get ERR_RUBY_READ_CME_MAX_EP regularly, we may need to raise it.
32-
#define MAX_EP_CHECKS 10
33+
#define MAX_EP_CHECKS 10
3334

3435
// Constants related to reading a method entry
3536
// https://github.com/ruby/ruby/blob/523857bfcb0f0cdfd1ed7faa09b9c59a0266e7e2/method.h#L118
@@ -271,8 +272,9 @@ static EBPF_INLINE ErrorCode read_ruby_frame(
271272
// frames will almost certainly be incorrect for Ruby versions < 2.6.
272273
frame_type = RUBY_FRAME_TYPE_CME_CFUNC;
273274
} else if (record->rubyUnwindState.jit_detected) {
274-
// If we detected a jit frame and are now in a cfunc, push the c frame
275-
// as we can no longer unwind native anymore
275+
// JIT is active but frame pointers are not available, so we cannot unwind
276+
// through JIT frames to get back to native code. Push the cfunc inline
277+
// instead of handing off to the native unwinder.
276278
frame_type = RUBY_FRAME_TYPE_CME_CFUNC;
277279
} else {
278280
// We save this cfp on in the "Record" entry, and when we start the unwinder
@@ -450,20 +452,19 @@ static EBPF_INLINE ErrorCode walk_ruby_stack(
450452
record->rubyUnwindState.cfunc_saved_frame = 0;
451453
}
452454

453-
if (
454-
rubyinfo->jit_start > 0 && record->state.pc >= rubyinfo->jit_start &&
455-
record->state.pc < rubyinfo->jit_end) {
455+
// Detect if the CPU PC is in the JIT region.
456+
bool in_jit = rubyinfo->jit_start > 0 && record->state.pc >= rubyinfo->jit_start &&
457+
record->state.pc < rubyinfo->jit_end;
458+
459+
if (in_jit) {
456460
record->rubyUnwindState.jit_detected = true;
457461

458-
// If the first frame is a jit PC, the leaf ruby frame should be the jit "owner"
459-
// the cpu PC is also pushed as the address,
460-
// as in theory this can be used to symbolize the JIT frame later
461-
if (trace->num_frames == 0) {
462-
ErrorCode error =
463-
push_ruby(&record->state, trace, RUBY_FRAME_TYPE_JIT, (u64)record->state.pc, 0, 0);
464-
if (error) {
465-
return error;
466-
}
462+
// Push a JIT frame with the raw machine PC. This can be used to
463+
// symbolize the JIT frame via perf map later.
464+
ErrorCode jit_error =
465+
push_ruby(&record->state, trace, RUBY_FRAME_TYPE_JIT, (u64)record->state.pc, 0, 0);
466+
if (jit_error) {
467+
return jit_error;
467468
}
468469
}
469470

@@ -474,8 +475,8 @@ static EBPF_INLINE ErrorCode walk_ruby_stack(
474475

475476
if (last_stack_frame <= stack_ptr) {
476477
// We have processed all frames in the Ruby VM and can stop here.
477-
// if this process has been JIT'd, the PC is invalid and we cannot resume native unwinding so
478-
// we are done
478+
// If JIT was detected, the PC is in the JIT region and native
479+
// unwinding would fail, so we stop.
479480
*next_unwinder = record->rubyUnwindState.jit_detected ? PROG_UNWIND_STOP : PROG_UNWIND_NATIVE;
480481
goto save_state;
481482
} else {

support/ebpf/tracer.ebpf.amd64

-136 Bytes
Binary file not shown.

support/ebpf/tracer.ebpf.arm64

-128 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)