summaryrefslogtreecommitdiff
path: root/libunwind
diff options
context:
space:
mode:
authorMartin Storsjo <martin@martin.st>2018-12-18 20:05:59 +0000
committerMartin Storsjo <martin@martin.st>2018-12-18 20:05:59 +0000
commit908fe1fabebd52126549d30ae6e11695f3ed1d20 (patch)
tree1caa7a2575330d12ce8becfaebc46788d4f7a06d /libunwind
parent1803294fea8466c72919f866c603bca4c6de9cd2 (diff)
[SEH] Add initial support for AArch64
This doesn't yet implement inspecting the .pdata/.xdata to find the LSDA pointer (in UnwindCursor::getInfoFromSEH), but normal C++ exception handling seems to run just fine without it. (The only place I can see where it's even referenced is in unwind_phase2_forced, and I can't find a codepath where libcxxabi would end up calling that.) Differential Revision: https://reviews.llvm.org/D55674
Diffstat (limited to 'libunwind')
-rw-r--r--libunwind/include/__libunwind_config.h6
-rw-r--r--libunwind/src/Unwind-seh.cpp18
-rw-r--r--libunwind/src/UnwindCursor.hpp53
3 files changed, 75 insertions, 2 deletions
diff --git a/libunwind/include/__libunwind_config.h b/libunwind/include/__libunwind_config.h
index a1e2f6de13a..54509495c38 100644
--- a/libunwind/include/__libunwind_config.h
+++ b/libunwind/include/__libunwind_config.h
@@ -57,7 +57,11 @@
# elif defined(__aarch64__)
# define _LIBUNWIND_TARGET_AARCH64 1
# define _LIBUNWIND_CONTEXT_SIZE 66
-# define _LIBUNWIND_CURSOR_SIZE 78
+# if defined(__SEH__)
+# define _LIBUNWIND_CURSOR_SIZE 164
+# else
+# define _LIBUNWIND_CURSOR_SIZE 78
+# endif
# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64
# elif defined(__arm__)
# define _LIBUNWIND_TARGET_ARM 1
diff --git a/libunwind/src/Unwind-seh.cpp b/libunwind/src/Unwind-seh.cpp
index 73a950a1913..c5cf7c47d40 100644
--- a/libunwind/src/Unwind-seh.cpp
+++ b/libunwind/src/Unwind-seh.cpp
@@ -87,6 +87,8 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx,
disp->ContextRecord->Rdx = ms_exc->ExceptionInformation[3];
#elif defined(__arm__)
disp->ContextRecord->R1 = ms_exc->ExceptionInformation[3];
+#elif defined(__aarch64__)
+ disp->ContextRecord->X1 = ms_exc->ExceptionInformation[3];
#endif
}
// This is the collided unwind to the landing pad. Nothing to do.
@@ -172,12 +174,16 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx,
exc->private_[2] = disp->TargetPc;
unw_get_reg(&cursor, UNW_ARM_R0, &retval);
unw_get_reg(&cursor, UNW_ARM_R1, &exc->private_[3]);
+#elif defined(__aarch64__)
+ exc->private_[2] = disp->TargetPc;
+ unw_get_reg(&cursor, UNW_ARM64_X0, &retval);
+ unw_get_reg(&cursor, UNW_ARM64_X1, &exc->private_[3]);
#endif
unw_get_reg(&cursor, UNW_REG_IP, &target);
ms_exc->ExceptionCode = STATUS_GCC_UNWIND;
#ifdef __x86_64__
ms_exc->ExceptionInformation[2] = disp->TargetIp;
-#elif defined(__arm__)
+#elif defined(__arm__) || defined(__aarch64__)
ms_exc->ExceptionInformation[2] = disp->TargetPc;
#endif
ms_exc->ExceptionInformation[3] = exc->private_[3];
@@ -447,6 +453,12 @@ _unw_init_seh(unw_cursor_t *cursor, CONTEXT *context) {
auto *co = reinterpret_cast<AbstractUnwindCursor *>(cursor);
co->setInfoBasedOnIPRegister();
return UNW_ESUCCESS;
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+ new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_arm64>(
+ context, LocalAddressSpace::sThisAddressSpace);
+ auto *co = reinterpret_cast<AbstractUnwindCursor *>(cursor);
+ co->setInfoBasedOnIPRegister();
+ return UNW_ESUCCESS;
#else
return UNW_EINVAL;
#endif
@@ -458,6 +470,8 @@ _unw_seh_get_disp_ctx(unw_cursor_t *cursor) {
return reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_x86_64> *>(cursor)->getDispatcherContext();
#elif defined(_LIBUNWIND_TARGET_ARM)
return reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm> *>(cursor)->getDispatcherContext();
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+ return reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm64> *>(cursor)->getDispatcherContext();
#else
return nullptr;
#endif
@@ -469,6 +483,8 @@ _unw_seh_set_disp_ctx(unw_cursor_t *cursor, DISPATCHER_CONTEXT *disp) {
reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_x86_64> *>(cursor)->setDispatcherContext(disp);
#elif defined(_LIBUNWIND_TARGET_ARM)
reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm> *>(cursor)->setDispatcherContext(disp);
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+ reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm64> *>(cursor)->setDispatcherContext(disp);
#endif
}
diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp
index 9791095ad15..a1308069184 100644
--- a/libunwind/src/UnwindCursor.hpp
+++ b/libunwind/src/UnwindCursor.hpp
@@ -615,6 +615,13 @@ UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
d.d = r.getFloatRegister(i);
_msContext.D[i - UNW_ARM_D0] = d.w;
}
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+ for (int i = UNW_ARM64_X0; i <= UNW_ARM64_X30; ++i)
+ _msContext.X[i - UNW_ARM64_X0] = r.getRegister(i);
+ _msContext.Sp = r.getRegister(UNW_REG_SP);
+ _msContext.Pc = r.getRegister(UNW_REG_IP);
+ for (int i = UNW_ARM64_D0; i <= UNW_ARM64_D31; ++i)
+ _msContext.V[i - UNW_ARM64_D0].D[0] = r.getFloatRegister(i);
#endif
}
@@ -638,6 +645,8 @@ bool UnwindCursor<A, R>::validReg(int regNum) {
if (regNum >= UNW_X86_64_RAX && regNum <= UNW_X86_64_R15) return true;
#elif defined(_LIBUNWIND_TARGET_ARM)
if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15) return true;
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+ if (regNum >= UNW_ARM64_X0 && regNum <= UNW_ARM64_X30) return true;
#endif
return false;
}
@@ -683,6 +692,10 @@ unw_word_t UnwindCursor<A, R>::getReg(int regNum) {
case UNW_ARM_LR: return _msContext.Lr;
case UNW_REG_IP:
case UNW_ARM_IP: return _msContext.Pc;
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+ case UNW_REG_SP: return _msContext.Sp;
+ case UNW_REG_IP: return _msContext.Pc;
+ default: return _msContext.X[regNum - UNW_ARM64_X0];
#endif
}
_LIBUNWIND_ABORT("unsupported register");
@@ -729,6 +742,40 @@ void UnwindCursor<A, R>::setReg(int regNum, unw_word_t value) {
case UNW_ARM_LR: _msContext.Lr = value; break;
case UNW_REG_IP:
case UNW_ARM_IP: _msContext.Pc = value; break;
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+ case UNW_REG_SP: _msContext.Sp = value; break;
+ case UNW_REG_IP: _msContext.Pc = value; break;
+ case UNW_ARM64_X0:
+ case UNW_ARM64_X1:
+ case UNW_ARM64_X2:
+ case UNW_ARM64_X3:
+ case UNW_ARM64_X4:
+ case UNW_ARM64_X5:
+ case UNW_ARM64_X6:
+ case UNW_ARM64_X7:
+ case UNW_ARM64_X8:
+ case UNW_ARM64_X9:
+ case UNW_ARM64_X10:
+ case UNW_ARM64_X11:
+ case UNW_ARM64_X12:
+ case UNW_ARM64_X13:
+ case UNW_ARM64_X14:
+ case UNW_ARM64_X15:
+ case UNW_ARM64_X16:
+ case UNW_ARM64_X17:
+ case UNW_ARM64_X18:
+ case UNW_ARM64_X19:
+ case UNW_ARM64_X20:
+ case UNW_ARM64_X21:
+ case UNW_ARM64_X22:
+ case UNW_ARM64_X23:
+ case UNW_ARM64_X24:
+ case UNW_ARM64_X25:
+ case UNW_ARM64_X26:
+ case UNW_ARM64_X27:
+ case UNW_ARM64_X28:
+ case UNW_ARM64_FP:
+ case UNW_ARM64_LR: _msContext.X[regNum - UNW_ARM64_X0] = value; break;
#endif
default:
_LIBUNWIND_ABORT("unsupported register");
@@ -740,6 +787,8 @@ bool UnwindCursor<A, R>::validFloatReg(int regNum) {
#if defined(_LIBUNWIND_TARGET_ARM)
if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) return true;
if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) return true;
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+ if (regNum >= UNW_ARM64_D0 && regNum <= UNW_ARM64_D31) return true;
#endif
return false;
}
@@ -764,6 +813,8 @@ unw_fpreg_t UnwindCursor<A, R>::getFloatReg(int regNum) {
return d.d;
}
_LIBUNWIND_ABORT("unsupported float register");
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+ return _msContext.V[regNum - UNW_ARM64_D0].D[0];
#else
_LIBUNWIND_ABORT("float registers unimplemented");
#endif
@@ -789,6 +840,8 @@ void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) {
_msContext.D[regNum - UNW_ARM_D0] = d.w;
}
_LIBUNWIND_ABORT("unsupported float register");
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+ _msContext.V[regNum - UNW_ARM64_D0].D[0] = value;
#else
_LIBUNWIND_ABORT("float registers unimplemented");
#endif