Commit 70509d1
committed
Merge commit 6b0a46958c56 from llvm-project (by Piotr Kubaj):
[libunwind][PPC64] Fix unw_getcontext corrupting callee-saved VSX registers on LE (#198371)
This is the first of two independent fixes for libunwind on ppc64le
(ELFv2 ABI, little-endian), where two separate bugs together cause
SIGSEGV during backtracing. This commit addresses the VSX register
corruption; the TOC-restore fault is handled in a follow-up. Both
were discovered while debugging lang/rust build failures with
RUST_BACKTRACE=1 on FreeBSD/powerpc64le (IBM POWER9).
On ppc64le, `unw_getcontext` saves each VS register with an in-place
`xxswapd n, n` followed by `stxvd2x`. The swap is needed because
`stxvd2x` stores doublewords in the wrong order on LE. However, the
macro never applies a second `xxswapd` to restore the register after
the store, so all 64 VS registers are permanently corrupted on return
from `unw_getcontext`.
This affects every callee-saved VSX register: f14-f31 (VSR14-VSR31)
and VR20-VR31 (VSR52-VSR63). After `_Unwind_Backtrace` returns, any
code that uses these registers sees wrong values. In practice this
manifests as SIGSEGV inside hashbrown's `reserve_rehash`: VR20-VR31
are corrupted before a SIMD comparison loop runs, producing an
out-of-bounds access.
Fix: add a second `xxswapd n, n` after the `stxvd2x` store. Since
`xxswapd` is its own inverse, the pair is a no-op on the architectural
register while still writing the correctly byte-swapped value to memory.
MFC after: 1 week1 parent c6f5d8f commit 70509d1
1 file changed
Lines changed: 4 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
418 | 418 | | |
419 | 419 | | |
420 | 420 | | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
421 | 424 | | |
422 | 425 | | |
423 | 426 | | |
| 427 | + | |
424 | 428 | | |
425 | 429 | | |
426 | 430 | | |
| |||
0 commit comments