Skip to content

ruby: support EC offset extraction for statically-linked Ruby#28

Closed
dalehamel wants to merge 3 commits into
mainfrom
ruby-static-ec-tls-offset
Closed

ruby: support EC offset extraction for statically-linked Ruby#28
dalehamel wants to merge 3 commits into
mainfrom
ruby-static-ec-tls-offset

Conversation

@dalehamel
Copy link
Copy Markdown
Member

@dalehamel dalehamel commented Mar 2, 2026

superseded by open-telemetry#1227

@dalehamel
Copy link
Copy Markdown
Member Author

Coredump Test Plan

This PR needs a coredump test for a statically-linked Ruby binary (no libruby.so) to exercise the binRubyRegex match and extractEcTLSOffset() disassembly path.

Test: ruby-3.4.7-static-loop (amd64 + arm64)

Build:

ruby-install ruby 3.4.7 -- --disable-shared

Verify the binary is static (no libruby.so):

ldd /opt/rubies/ruby-3.4.7/bin/ruby
# Should show no libruby.so dependency
readelf -s /opt/rubies/ruby-3.4.7/bin/ruby | grep rb_current_ec_noinline
# Should exist — this is the function we disassemble

Capture:

chruby ruby-3.4.7  # the --disable-shared build
ruby tools/coredump/testsources/ruby/loop.rb &
PID=$!
sleep 2
./coredump new -pid $PID -name ruby-3.4.7-static-loop

What this exercises

  • binRubyRegex matches bin/ruby instead of libruby*.so
  • extractEcTLSOffset() disassembles rb_current_ec_noinline to find the direct TP-relative offset (e.g. FS:0xfffffffffffffff8 on x86_64, MRS tpidr_el0 + ADD #0x38 on aarch64)
  • The signed current_ec_tpbase_tls_offset (s64) is used with tsd_base to read ruby_current_ec
  • Expected frames should be identical in shape to existing ruby-3.4.x-loop tests

Files to add

  • tools/coredump/testdata/amd64/ruby-3.4.7-static-loop.json
  • tools/coredump/testdata/arm64/ruby-3.4.7-static-loop.json

@dalehamel dalehamel force-pushed the ruby-static-ec-tls-offset branch from c3ca8b5 to 64117f2 Compare March 3, 2026 15:10
@dalehamel dalehamel changed the base branch from libcinfo-tsd-tls-refactor to main March 3, 2026 15:10
For statically-linked Ruby binaries (bin/ruby rather than libruby.so),
TLS descriptors are not available. Instead, rb_current_ec_noinline
accesses the execution context directly via a TP-relative offset
(FS:offset on x86_64, MRS tpidr_el0 + ADD on aarch64).

This reuses the asm/amd.ExtractTLSOffset and asm/arm.ExtractTLSOffset
infrastructure from the Python TLS PR (open-telemetry#1109) to disassemble
rb_current_ec_noinline and extract the offset.

Also changes current_ec_tpbase_tls_offset from u64 to s64 since
static TLS offsets (local exec model) are negative on x86_64.

Also adds RUBY_DISABLE_GC env var support to the loop.rb test script
to allow capturing coredumps without GC interference.
@dalehamel dalehamel force-pushed the ruby-static-ec-tls-offset branch 7 times, most recently from cfb41a7 to c881316 Compare March 4, 2026 16:45
Adds coredump tests for a statically-linked Ruby 3.4.7 binary on both
arm64 and amd64, exercising the binRubyRegex match and
extractEcTLSOffset() disassembly path for finding ruby_current_ec
via direct TP-relative offset.

Captured via gdb attach + breakpoint on rb_vm_exec to ensure a clean
snapshot deep in the Ruby VM stack.
@dalehamel dalehamel force-pushed the ruby-static-ec-tls-offset branch from c881316 to a2ccaf1 Compare March 4, 2026 17:02
@dalehamel
Copy link
Copy Markdown
Member Author

merged upstream 🎉

@dalehamel dalehamel closed this Mar 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant