Skip to content

Commit

Permalink
[SEH] Add initial support for AArch64
Browse files Browse the repository at this point in the history
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
  • Loading branch information
mstorsjo committed Dec 18, 2018
1 parent 18a9d54 commit 09cf637
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 2 deletions.
6 changes: 5 additions & 1 deletion libunwind/include/__libunwind_config.h
Expand Up @@ -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
Expand Down
18 changes: 17 additions & 1 deletion libunwind/src/Unwind-seh.cpp
Expand Up @@ -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.
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
}

Expand Down
53 changes: 53 additions & 0 deletions libunwind/src/UnwindCursor.hpp
Expand Up @@ -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
}

Expand All @@ -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;
}
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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");
Expand All @@ -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;
}
Expand All @@ -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
Expand All @@ -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
Expand Down

0 comments on commit 09cf637

Please sign in to comment.