Skip to content

Fix indirect fixup handling on aarch64 via frame-pointer-anchored scan#9803

Open
mszabo-wikia wants to merge 1 commit into
facebook:masterfrom
mszabo-wikia:aarch64-indirect-fixups-fix
Open

Fix indirect fixup handling on aarch64 via frame-pointer-anchored scan#9803
mszabo-wikia wants to merge 1 commit into
facebook:masterfrom
mszabo-wikia:aarch64-indirect-fixups-fix

Conversation

@mszabo-wikia

Copy link
Copy Markdown
Contributor

Running hhvm hphp/test/quick/dv.php on aarch64 with HHVM compiled in release mode consistently segfaults while syncing the VM state prior to producing a backtrace for a Hack exception (see gist).[1]

The crash happens because fixupWork assumes that aligned native frames directly follow one another as it traverses the chain of frame pointers while looking for the first VM frame, so it ends up using an incorrect CFA for the reconstructed VM frame. But since https://reviews.llvm.org/D65653, clang in release builds may decide to place locals above the frame record, breaking this assumption, as foretold in D29878492.

I tried switching this logic to use the unwinder in D92892655 but that proved to be prohibitively unperformant. However, since we know that the target of the indirect fixup is associated with the first VM frame which is also the next frame, we can scan the stack upwards looking for the first ActRec whose m_sfp matches the stored FP for that frame and whose m_savedRip resolves to a valid non-indirect fixup. For unpadded frames this just stops on the first iteration step.

[1] https://gist.github.com/mszabo-wikia/187833ee32cd5b6f4efa8bd987a66cd4

Running `hhvm hphp/test/quick/dv.php` on aarch64 with HHVM compiled in
release mode consistently segfaults while syncing the VM state prior to
producing a backtrace for a Hack exception (see gist).[1]

The crash happens because fixupWork assumes that aligned native frames
directly follow one another as it traverses the chain of frame pointers
while looking for the first VM frame, so it ends up using an incorrect
CFA for the reconstructed VM frame. But since https://reviews.llvm.org/D65653,
clang in release builds may decide to place locals above the frame record,
breaking this assumption, as foretold in D29878492.

I tried switching this logic to use the unwinder in D92892655 but that
proved to be prohibitively unperformant. However, since we know that
the target of the indirect fixup is associated with the first VM frame
which is also the next frame, we can scan the stack upwards looking for
the first ActRec whose `m_sfp` matches the stored FP for that frame
and whose `m_savedRip` resolves to a valid non-indirect fixup.
For unpadded frames this just stops on the first iteration step.

[1] https://gist.github.com/mszabo-wikia/187833ee32cd5b6f4efa8bd987a66cd4
@meta-cla meta-cla Bot added the CLA Signed label Jun 17, 2026
@meta-codesync

meta-codesync Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

This pull request has been imported. If you are a Meta employee, you can view this in D108886444. (Because this pull request was imported automatically, there will not be any future comments.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant