diff --git a/interpreter/nodev8/v8.go b/interpreter/nodev8/v8.go index 72b42ffb9..1b2345a36 100644 --- a/interpreter/nodev8/v8.go +++ b/interpreter/nodev8/v8.go @@ -966,6 +966,26 @@ func (i *v8Instance) analyzeScopeInfo(ptr libpf.Address) (name libpf.String, return libpf.NullString, 0, 0 } + // Starting in this version, position start and end + // were moved to fixed locations before the variable-length data, + // so we no longer need a heuristic to find them (and in fact, our + // heuristic doesn't work). + // See https://chromium-review.googlesource.com/c/v8/v8/+/5627032 + // for where the change was made. + isOld := i.d.version < v8Ver(12, 8, 44) + if !isOld { + // As of today [2026-05-13] these haven't changed since + // they were introduced [2024-06-13]. That's scarcely two years, + // so maybe they'll change in the future; at any rate, there doesn't seem to be a way to + // derive them from symbols. + // + // See https://chromium.googlesource.com/v8/v8.git/+/refs/tags/12.8.44/src/objects/scope-info.tq#125 + positionInfoStartIdx := 3 + positionInfoEndIdx := 4 + + startPos = int(npsr.Uint64(slotData, uint(positionInfoStartIdx*slotSize))) + endPos = int(npsr.Uint64(slotData, uint(positionInfoEndIdx*slotSize))) + } // Skip reserved slots and the context locals ndx := int(vms.ScopeInfoIndex.FirstVars) ndx += 2 * int(decodeSMI(npsr.Uint64(slotData, @@ -980,7 +1000,12 @@ func (i *v8Instance) analyzeScopeInfo(ptr libpf.Address) (name libpf.String, // assume that first valid string is the function name name, _ = i.getString(libpf.Address(cur), 0) } - if isSMI(cur) && isSMI(prev) { + // In recent versions, we'll have already found the begin/end positions at + // fixed indices, so just return. See the comment where isOld is defined for details. + if !isOld && name != libpf.NullString { + return name, startPos, endPos + } + if isOld && isSMI(cur) && isSMI(prev) { // Assume that two numbers (first one lower than the second) // is the start/end position pair. This also follows after // function name, so break when found. @@ -992,6 +1017,10 @@ func (i *v8Instance) analyzeScopeInfo(ptr libpf.Address) (name libpf.String, } prev = cur } + if !isOld { + // even if we didn't find name, we can be reasonably sure start/end are right, so return them + return name, startPos, endPos + } return name, 0, 0 } diff --git a/tools/coredump/testdata/arm64/node-hidden-internal-symbols.json b/tools/coredump/testdata/arm64/node-hidden-internal-symbols.json index 60d2a7178..eba710d6f 100644 --- a/tools/coredump/testdata/arm64/node-hidden-internal-symbols.json +++ b/tools/coredump/testdata/arm64/node-hidden-internal-symbols.json @@ -13,7 +13,7 @@ "node+0xb42107", "node+0xa46483", "V8::UnknownFrame+0 in :0", - "utf8+0 in /local/hello3.js:0", + "utf8+0 in /local/hello3.js:1", "+0 in node:internal/modules/cjs/loader:0", "+0 in node:internal/modules/cjs/loader:0", "+0 in node:internal/modules/cjs/loader:0",