diff --git a/interpreter/ruby/ruby.go b/interpreter/ruby/ruby.go index eb278bfdd..ea1055357 100644 --- a/interpreter/ruby/ruby.go +++ b/interpreter/ruby/ruby.go @@ -1258,9 +1258,9 @@ func Loader(ebpf interpreter.EbpfHandler, info *interpreter.LoaderInfo) (interpr // Reason for lowest supported version: // - Ruby 2.5 is still commonly used at time of writing this code. // https://www.jetbrains.com/lp/devecosystem-2020/ruby/ - // Reason for maximum supported version 3.5.x: - // - this is currently the newest stable version - minVer, maxVer := rubyVersion(2, 5, 0), rubyVersion(3, 6, 0) + // Reason for maximum supported version 4.0.x: + // - Ruby 4.0 was released December 2025 with ZJIT and redesigned Ractor Port API + minVer, maxVer := rubyVersion(2, 5, 0), rubyVersion(4, 1, 0) if version < minVer || version >= maxVer { return nil, fmt.Errorf("unsupported Ruby %d.%d.%d (need >= %d.%d.%d and <= %d.%d.%d)", (version>>16)&0xff, (version>>8)&0xff, version&0xff, @@ -1387,6 +1387,13 @@ func Loader(ebpf interpreter.EbpfHandler, info *interpreter.LoaderInfo) (interpr vms.rclass_and_rb_classext_t.classext = 32 vms.rb_classext_struct.as_singleton_class_attached_object = 96 vms.rb_classext_struct.classpath = 120 + case version >= rubyVersion(4, 0, 0) && version < rubyVersion(4, 1, 0): + rid.hasClassPath = true + rid.rubyFlSingleton = libpf.Address(RUBY_FL_USER1) + + vms.rclass_and_rb_classext_t.classext = 24 + vms.rb_classext_struct.as_singleton_class_attached_object = 112 + vms.rb_classext_struct.classpath = 128 default: rid.hasClassPath = true rid.rubyFlSingleton = libpf.Address(RUBY_FL_USER1) @@ -1407,6 +1414,8 @@ func Loader(ebpf interpreter.EbpfHandler, info *interpreter.LoaderInfo) (interpr rid.lastOpId = 169 case version < rubyVersion(3, 5, 0): rid.lastOpId = 170 + case version < rubyVersion(4, 1, 0): + rid.lastOpId = 171 default: rid.lastOpId = 170 } @@ -1452,6 +1461,14 @@ func Loader(ebpf interpreter.EbpfHandler, info *interpreter.LoaderInfo) (interpr vms.vm_struct.gc_objspace = 1320 } vms.objspace.flags = 16 + case version >= rubyVersion(4, 0, 0) && version < rubyVersion(4, 1, 0): + rid.hasObjspace = true + if runtime.GOARCH == "amd64" { + vms.vm_struct.gc_objspace = 1248 + } else { + vms.vm_struct.gc_objspace = 1272 + } + vms.objspace.flags = 28 default: rid.hasObjspace = true vms.objspace.flags = 20 @@ -1515,6 +1532,17 @@ func Loader(ebpf interpreter.EbpfHandler, info *interpreter.LoaderInfo) (interpr vms.iseq_constant_body.succ_index_table = 136 vms.iseq_constant_body.local_iseq = 168 vms.iseq_constant_body.size_of_iseq_constant_body = 352 + case version >= rubyVersion(4, 0, 0) && version < rubyVersion(4, 1, 0): + // Ruby 4.0+ has different struct layout due to JIT refactoring + // and other internal changes. + vms.iseq_constant_body.insn_info_body = 112 + vms.iseq_constant_body.insn_info_size = 128 + vms.iseq_constant_body.succ_index_table = 136 + vms.iseq_constant_body.local_iseq = 176 + // The JIT fields at the end of the struct get added if you have rustc installed or are otherwise build config dependent. + // 304 is the size without them and the "common" size regardless of config. + // It is safer to set this to the smaller value, especially since the highest field we actually access is much lower + vms.iseq_constant_body.size_of_iseq_constant_body = 304 default: // 3.3.x and 3.5.x have the same values vms.iseq_constant_body.insn_info_body = 112 vms.iseq_constant_body.insn_info_size = 128 @@ -1588,7 +1616,15 @@ func Loader(ebpf interpreter.EbpfHandler, info *interpreter.LoaderInfo) (interpr vms.rb_symbols_t.ids = 16 if version >= rubyVersion(3, 0, 0) { - if version >= rubyVersion(3, 3, 0) { + if version >= rubyVersion(4, 0, 0) { + // Ruby 4.0+ redesigned rb_ractor_sync with Port-based API. + // Offsets determined via GDB analysis of rb_ractor_struct. + if runtime.GOARCH == "amd64" { + vms.rb_ractor_struct.running_ec = 0x138 + } else { + vms.rb_ractor_struct.running_ec = 0x148 + } + } else if version >= rubyVersion(3, 3, 0) { if runtime.GOARCH == "amd64" { vms.rb_ractor_struct.running_ec = 0x180 } else { diff --git a/tools/coredump/testdata/amd64/ruby-4.0.1-loop.json b/tools/coredump/testdata/amd64/ruby-4.0.1-loop.json new file mode 100644 index 000000000..ae95cb4e6 --- /dev/null +++ b/tools/coredump/testdata/amd64/ruby-4.0.1-loop.json @@ -0,0 +1,95 @@ +{ + "coredump-ref": "a9472d159e9def7bc2ca7e5286e5175619d0978f45d35e7382cbeb43ed9c3c18", + "threads": [ + { + "lwp": 13967, + "frames": [ + "libruby.so.4.0.1+0x328510", + "libruby.so.4.0.1+0x34e01b", + "libruby.so.4.0.1+0x34edb9", + "libruby.so.4.0.1+0x3516b4", + "libruby.so.4.0.1+0x1c2446", + "libruby.so.4.0.1+0x11a11f", + "libruby.so.4.0.1+0x32bfec", + "libruby.so.4.0.1+0x335772", + "libruby.so.4.0.1+0x34435d", + "libruby.so.4.0.1+0x348923", + "libruby.so.4.0.1+0x34da1f", + "libruby.so.4.0.1+0x23f1ed", + "libruby.so.4.0.1+0x32bfec", + "libruby.so.4.0.1+0x335772", + "libruby.so.4.0.1+0x34435d", + "Enumerator::ArithmeticSequence#each+0 in :0", + "Object#is_prime+0 in /tmp/loop.rb:10", + "Object#sum_of_primes+0 in /tmp/loop.rb:19", + "libruby.so.4.0.1+0x348923", + "libruby.so.4.0.1+0x34da1f", + "libruby.so.4.0.1+0x23f1ed", + "libruby.so.4.0.1+0x32bfec", + "libruby.so.4.0.1+0x335772", + "libruby.so.4.0.1+0x34435d", + "Range#each+0 in :0", + "Object#sum_of_primes+0 in /tmp/loop.rb:18", + "?+0x0", + "libruby.so.4.0.1+0x348923", + "libruby.so.4.0.1+0x12bd24", + "libruby.so.4.0.1+0x13022a", + "ruby+0x1185", + "libc.so.6+0x2a1c9", + "libc.so.6+0x2a28a", + "ruby+0x11d4" + ] + }, + { + "lwp": 13983, + "frames": [ + "libc.so.6+0x12a072", + "libruby.so.4.0.1+0x2e5873", + "libc.so.6+0x9caa3", + "libc.so.6+0x129c6b" + ] + } + ], + "modules": [ + { + "ref": "829c92e26260412dfdd414e989144e57c1e2c29d5c5a9c299373fb6947e8438c", + "local-path": "/home/liad.linux/.rbenv/versions/4.0.1/bin/ruby" + }, + { + "ref": "511f825ee075610ac9c0f7f91e2c13de2000d0f7b859f6461137e809a0a009d0", + "local-path": "/usr/lib/x86_64-linux-gnu/libc.so.6" + }, + { + "ref": "f06f2ce1f1833df5f41cf13b6447ff07bea993ad9b27297d3428c2f70ab3f0e7", + "local-path": "/usr/lib/x86_64-linux-gnu/libm.so.6" + }, + { + "ref": "759e56c545b4a4c34a6ab9d0be9da8f2406824aee37db8178162b5916e32e70d", + "local-path": "/home/liad.linux/.rbenv/versions/4.0.1/lib/libruby.so.4.0.1" + }, + { + "ref": "ed53deb1ff75db1f7215b7499b906048d7f22ade66c201206489528b1270bf87", + "local-path": "/home/liad.linux/.rbenv/versions/4.0.1/lib/ruby/4.0.0/x86_64-linux/monitor.so" + }, + { + "ref": "588d492660cceeb95955c1d2af4b6e828a9294713192c44d42f205a84c562d64", + "local-path": "/home/liad.linux/.rbenv/versions/4.0.1/lib/ruby/4.0.0/x86_64-linux/enc/encdb.so" + }, + { + "ref": "1502636e3be8232c9cf801dfb533694aea985d449904f3e1295db26d7b348946", + "local-path": "/usr/lib/x86_64-linux-gnu/libcrypt.so.1.1.0" + }, + { + "ref": "6222a16be7f2d458d6870efe6e715fc0c8d45766fb79cf7dcc3125538d703e28", + "local-path": "/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2" + }, + { + "ref": "30675893bbad819d6ce4368263a20c65dce58751c2a891d61a7957a1da7281e7", + "local-path": "/home/liad.linux/.rbenv/versions/4.0.1/lib/ruby/4.0.0/x86_64-linux/enc/trans/transdb.so" + }, + { + "ref": "9b64150b28505a33d6bc3ecf709c279f6de97a1c184dbda65d06ee4537f6d286", + "local-path": "/usr/lib/x86_64-linux-gnu/libz.so.1.3" + } + ] +} diff --git a/tools/coredump/testdata/arm64/ruby-4.0.1-loop.json b/tools/coredump/testdata/arm64/ruby-4.0.1-loop.json new file mode 100644 index 000000000..42513a53b --- /dev/null +++ b/tools/coredump/testdata/arm64/ruby-4.0.1-loop.json @@ -0,0 +1,90 @@ +{ + "coredump-ref": "70f9902fa22a105817994dd6c60b2390cef81370787fc92784670879ef0371a7", + "threads": [ + { + "lwp": 13420, + "frames": [ + "libruby.so.4.0.1+0x31e660", + "Object#is_prime+0 in /tmp/loop.rb:13", + "libruby.so.4.0.1+0x32102f", + "libruby.so.4.0.1+0x325aa3", + "libruby.so.4.0.1+0x220853", + "libruby.so.4.0.1+0x30a49b", + "libruby.so.4.0.1+0x310317", + "libruby.so.4.0.1+0x31dbc7", + "Range#each+0 in :0", + "Object#is_prime+0 in /tmp/loop.rb:12", + "Object#sum_of_primes+0 in /tmp/loop.rb:22", + "block (2 levels) in
+0 in /tmp/loop.rb:32", + "libruby.so.4.0.1+0x32110f", + "libruby.so.4.0.1+0x325aa3", + "libruby.so.4.0.1+0x2207bb", + "libruby.so.4.0.1+0x30a49b", + "libruby.so.4.0.1+0x310317", + "libruby.so.4.0.1+0x31dbc7", + "Range#each+0 in :0", + "block in
+0 in /tmp/loop.rb:31", + "Kernel#loop+0 in :169", + "
+0 in /tmp/loop.rb:30", + "libruby.so.4.0.1+0x32102f", + "libruby.so.4.0.1+0x11713f", + "libruby.so.4.0.1+0x11b133", + "ruby+0xb2f", + "libc.so.6+0x284c3", + "libc.so.6+0x28597", + "ruby+0xbaf" + ] + }, + { + "lwp": 13436, + "frames": [ + "libc.so.6+0xebe34", + "libruby.so.4.0.1+0x2c18bf", + "libc.so.6+0x8595b", + "libc.so.6+0xebb0b" + ] + } + ], + "modules": [ + { + "ref": "852537161fd8c2a3ba494dce16efce1cef280c75bdb9c49846a6d374d1542153", + "local-path": "/home/liad.linux/.rbenv/versions/4.0.1/lib/ruby/4.0.0/aarch64-linux/monitor.so" + }, + { + "ref": "d3a914675a800a45f7c9e10027f363c204572633e774a30b0162ea34a2a01532", + "local-path": "/home/liad.linux/.rbenv/versions/4.0.1/lib/ruby/4.0.0/aarch64-linux/enc/trans/transdb.so" + }, + { + "ref": "8adbdb89cee46da7b3530518b5f89822c069ace403f826a8dbea41fe0657a399", + "local-path": "/home/liad.linux/.rbenv/versions/4.0.1/lib/ruby/4.0.0/aarch64-linux/enc/encdb.so" + }, + { + "ref": "f572bd122e2b3b14d2f9d8d4345e1351fd9fbf26f9402e3e42ef36b65f833411", + "local-path": "/usr/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1" + }, + { + "ref": "a33d6d847c58e0f1b2c378fd8f2d359d146235e558cb62d9cc8b428d806f95bd", + "local-path": "/home/liad.linux/.rbenv/versions/4.0.1/bin/ruby" + }, + { + "ref": "2fd7c8f96a208532befb77cec1cfee8a08217a97b77d8eed382537fa6cc6e72c", + "local-path": "/usr/lib/aarch64-linux-gnu/libc.so.6" + }, + { + "ref": "ac92dc80c7d902e3852986e858ba682a981c15a12ec0e163bd4d56dde9b3dd6e", + "local-path": "/usr/lib/aarch64-linux-gnu/libm.so.6" + }, + { + "ref": "b41cebf0be70f869bf60228cb5761f875ced865b0f4016f544d82f7a9ded28b0", + "local-path": "/usr/lib/aarch64-linux-gnu/libcrypt.so.1.1.0" + }, + { + "ref": "170380b4e7ab28ec86eb090b48df90f84089392cb72fecd5067e5b7a4dc5239f", + "local-path": "/usr/lib/aarch64-linux-gnu/libz.so.1.3" + }, + { + "ref": "b7bd46ea9c248260d6e19694930847ed8d6bb34941e2f688130842a0bf6d2c51", + "local-path": "/home/liad.linux/.rbenv/versions/4.0.1/lib/libruby.so.4.0.1" + } + ] +}