Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/lib/libunwind PR toolchain/55837
details: https://anonhg.NetBSD.org/src/rev/19c6ff6d5c13
branches: trunk
changeset: 983646:19c6ff6d5c13
user: rin <rin%NetBSD.org@localhost>
date: Mon May 31 12:12:24 2021 +0000
description:
PR toolchain/55837
Bump LAST_REGISTER and LAST_RESTORE_REG to REGNO_ARM32_S31 for arm.
There are two numbering schemes for VFPv2 registers: s0-s31 and d0-d15.
The former is used by GCC, and the latter is by LLVM. Since libunwind was
derived from LLVM, it has never supported the former. This results in
crashes for GCC-compiled binaries in exception handler of C++, if it
encounters VFPv2 registers when unwinding frames.
This commit adds support for s0-s31 numbering to libunwind. I choose an
implementation in which VFPv2 registers are ``double-counted'' as s0-s31
AND d0-d15. This does not cause real problems, since the former is only
used by GCC, and the later is by LLVM. That is, different numbering
schemes cannot appear in a same frame. To make sure, assertions are added
in order to check this.
I've confirmed that no regression for ATF both for GCC- and LLVM-compiled
userlands.
diffstat:
sys/lib/libunwind/Registers.hpp | 20 ++++++++++++++++++--
1 files changed, 18 insertions(+), 2 deletions(-)
diffs (51 lines):
diff -r 145964ebf8bc -r 19c6ff6d5c13 sys/lib/libunwind/Registers.hpp
--- a/sys/lib/libunwind/Registers.hpp Mon May 31 11:57:28 2021 +0000
+++ b/sys/lib/libunwind/Registers.hpp Mon May 31 12:12:24 2021 +0000
@@ -335,8 +335,8 @@
class Registers_arm32 {
public:
enum {
- LAST_REGISTER = REGNO_ARM32_D31,
- LAST_RESTORE_REG = REGNO_ARM32_D31,
+ LAST_REGISTER = REGNO_ARM32_S31,
+ LAST_RESTORE_REG = REGNO_ARM32_S31,
RETURN_OFFSET = 0,
RETURN_MASK = 0,
};
@@ -385,6 +385,14 @@
assert(validFloatVectorRegister(num));
const void *addr = reinterpret_cast<const void *>(addr_);
if (num >= REGNO_ARM32_S0 && num <= REGNO_ARM32_S31) {
+ /*
+ * XXX
+ * There are two numbering schemes for VFPv2 registers: s0-s31
+ * (used by GCC) and d0-d15 (used by LLVM). We won't support both
+ * schemes simultaneously in a same frame.
+ */
+ assert((flags & FLAGS_EXTENDED_VFPV2_REGNO) == 0);
+ flags |= FLAGS_LEGACY_VFPV2_REGNO;
if ((flags & FLAGS_VFPV2_USED) == 0) {
lazyVFPv2();
flags |= FLAGS_VFPV2_USED;
@@ -402,6 +410,12 @@
addr, sizeof(fpreg[0]) / 2);
} else {
if (num <= REGNO_ARM32_D15) {
+ /*
+ * XXX
+ * See XXX comment above.
+ */
+ assert((flags & FLAGS_LEGACY_VFPV2_REGNO) == 0);
+ flags |= FLAGS_EXTENDED_VFPV2_REGNO;
if ((flags & FLAGS_VFPV2_USED) == 0) {
lazyVFPv2();
flags |= FLAGS_VFPV2_USED;
@@ -428,6 +442,8 @@
enum {
FLAGS_VFPV2_USED = 0x1,
FLAGS_VFPV3_USED = 0x2,
+ FLAGS_LEGACY_VFPV2_REGNO = 0x4,
+ FLAGS_EXTENDED_VFPV2_REGNO = 0x8,
};
};
Home |
Main Index |
Thread Index |
Old Index