summaryrefslogtreecommitdiff
path: root/src/pal/src/exception/seh-unwind.cpp
diff options
context:
space:
mode:
authorJan Vorlicek <janvorli@microsoft.com>2018-10-10 14:00:28 -0700
committerGitHub <noreply@github.com>2018-10-10 14:00:28 -0700
commiteaf32b0359a414d8e218fb60e671a74524918237 (patch)
treee64a0d51b7607d7dd51c52f2d4e577ba7036c44d /src/pal/src/exception/seh-unwind.cpp
parent7dea3f558ee3193b8e7aeec064db79e2e8f92642 (diff)
downloadcoreclr-eaf32b0359a414d8e218fb60e671a74524918237.tar.gz
coreclr-eaf32b0359a414d8e218fb60e671a74524918237.tar.bz2
coreclr-eaf32b0359a414d8e218fb60e671a74524918237.zip
Fix unwind on ARM64 Linux (#20345)
The libunwind cannot unwind from `__libc_start_main` to `_start` on Linux ARM64 with glibc <= 2.27, because the `__libc_start_main` is missing unwind info. While we already have a way to detect such case when the same issue happens for `_start`, we were triggering it only in case unw_step returned 0. For this case, it returns 1 though, which is also a valid success indicator. The result is that .NET core starts spinning infinitely in case an unhandled exception happens on ARM64. The fix is to update the check to test for the return value being >= 0.
Diffstat (limited to 'src/pal/src/exception/seh-unwind.cpp')
-rw-r--r--src/pal/src/exception/seh-unwind.cpp13
1 files changed, 6 insertions, 7 deletions
diff --git a/src/pal/src/exception/seh-unwind.cpp b/src/pal/src/exception/seh-unwind.cpp
index 2b7c9360a6..c62f975d4e 100644
--- a/src/pal/src/exception/seh-unwind.cpp
+++ b/src/pal/src/exception/seh-unwind.cpp
@@ -329,14 +329,13 @@ BOOL PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextP
//
UnwindContextToWinContext(&cursor, context);
- // FreeBSD, NetBSD, OSX and Alpine appear to do two different things when unwinding
- // 1: If it reaches where it cannot unwind anymore, say a
- // managed frame. It will return 0, but also update the $pc
- // 2: If it unwinds all the way to _start it will return
- // 0 from the step, but $pc will stay the same.
+ // On some OSes / architectures if it unwound all the way to _start
+ // (__libc_start_main on arm64 Linux with glibc older than 2.27).
+ // >= 0 is returned from the step, but $pc will stay the same.
// So we detect that here and set the $pc to NULL in that case.
- // This is the default behavior of the libunwind on Linux.
- if (st == 0 && CONTEXTGetPC(context) == curPc)
+ // This is the default behavior of the libunwind on x64 Linux.
+ //
+ if (st >= 0 && CONTEXTGetPC(context) == curPc)
{
CONTEXTSetPC(context, 0);
}