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
44 changes: 40 additions & 4 deletions interpreter/ruby/ruby.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand All @@ -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
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
95 changes: 95 additions & 0 deletions tools/coredump/testdata/amd64/ruby-4.0.1-loop.json
Original file line number Diff line number Diff line change
@@ -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 <cfunc>: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 <cfunc>: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"
}
]
}
90 changes: 90 additions & 0 deletions tools/coredump/testdata/arm64/ruby-4.0.1-loop.json
Original file line number Diff line number Diff line change
@@ -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 <cfunc>:0",
"Object#is_prime+0 in /tmp/loop.rb:12",
"Object#sum_of_primes+0 in /tmp/loop.rb:22",
"block (2 levels) in <main>+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 <cfunc>:0",
"block in <main>+0 in /tmp/loop.rb:31",
"Kernel#loop+0 in <internal:kernel>:169",
"<main>+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"
}
]
}