[SEH] Add initial support for AArch64
authorMartin Storsjo <martin@martin.st>
Tue, 18 Dec 2018 20:05:59 +0000 (20:05 +0000)
committerMartin Storsjo <martin@martin.st>
Tue, 18 Dec 2018 20:05:59 +0000 (20:05 +0000)
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

llvm-svn: 349532

libunwind/include/__libunwind_config.h
libunwind/src/Unwind-seh.cpp
libunwind/src/UnwindCursor.hpp

index a1e2f6d..5450949 100644 (file)
 # 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
index 73a950a..c5cf7c4 100644 (file)
@@ -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
 }
 
index 9791095..a130806 100644 (file)
@@ -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