[libunwind][ARM] Handle end of stack during unwind

When unwind step reaches the end of the stack that means the force unwind should notify the stop function.
This is not an error, it could mean just the thread is cleaned up completely.

Reviewed By: #libunwind, mstorsjo

Differential Revision: https://reviews.llvm.org/D109856

GitOrigin-RevId: 632acec73776c4d6f7073d6de04ed6b8bfd36e6d
diff --git a/src/Unwind-EHABI.cpp b/src/Unwind-EHABI.cpp
index d3577c9..5959d2a 100644
--- a/src/Unwind-EHABI.cpp
+++ b/src/Unwind-EHABI.cpp
@@ -187,9 +187,14 @@
   if (result != _URC_CONTINUE_UNWIND)
     return result;
 
-  if (__unw_step(reinterpret_cast<unw_cursor_t *>(context)) != UNW_STEP_SUCCESS)
+  switch (__unw_step(reinterpret_cast<unw_cursor_t *>(context))) {
+  case UNW_STEP_SUCCESS:
+    return _URC_CONTINUE_UNWIND;
+  case UNW_STEP_END:
+    return _URC_END_OF_STACK;
+  default:
     return _URC_FAILURE;
-  return _URC_CONTINUE_UNWIND;
+  }
 }
 
 // Generates mask discriminator for _Unwind_VRS_Pop, e.g. for _UVRSC_CORE /
@@ -678,12 +683,13 @@
 unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
                      _Unwind_Exception *exception_object, _Unwind_Stop_Fn stop,
                      void *stop_parameter) {
+  bool endOfStack = false;
   // See comment at the start of unwind_phase1 regarding VRS integrity.
   __unw_init_local(cursor, uc);
   _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_force(ex_ojb=%p)",
                              static_cast<void *>(exception_object));
   // Walk each frame until we reach where search phase said to stop
-  while (true) {
+  while (!endOfStack) {
     // Update info about this frame.
     unw_proc_info_t frameInfo;
     if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
@@ -756,6 +762,14 @@
         // We may get control back if landing pad calls _Unwind_Resume().
         __unw_resume(cursor);
         break;
+      case _URC_END_OF_STACK:
+        _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
+                                   "personality returned "
+                                   "_URC_END_OF_STACK",
+                                   (void *)exception_object);
+        // Personalty routine did the step and it can't step forward.
+        endOfStack = true;
+        break;
       default:
         // Personality routine returned an unknown result code.
         _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
@@ -1133,9 +1147,14 @@
 __gnu_unwind_frame(_Unwind_Exception *exception_object,
                    struct _Unwind_Context *context) {
   unw_cursor_t *cursor = (unw_cursor_t *)context;
-  if (__unw_step(cursor) != UNW_STEP_SUCCESS)
+  switch (__unw_step(cursor)) {
+  case UNW_STEP_SUCCESS:
+    return _URC_OK;
+  case UNW_STEP_END:
+    return _URC_END_OF_STACK;
+  default:
     return _URC_FAILURE;
-  return _URC_OK;
+  }
 }
 
 #endif  // defined(_LIBUNWIND_ARM_EHABI)