This revision was automatically updated to reflect the committed changes.
Closed by commit rG632acec73776: [libunwind][ARM] Handle end of stack during
unwind (authored by danielkiss).
Herald added projects: libc++abi, libunwind.
Herald added 1 blocking reviewer(s): libc++abi.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D109856/new/
https://reviews.llvm.org/D109856
Files:
libcxxabi/src/cxa_personality.cpp
libcxxabi/test/forced_unwind3.pass.cpp
libunwind/src/Unwind-EHABI.cpp
Index: libunwind/src/Unwind-EHABI.cpp
===================================================================
--- libunwind/src/Unwind-EHABI.cpp
+++ libunwind/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)
Index: libcxxabi/test/forced_unwind3.pass.cpp
===================================================================
--- /dev/null
+++ libcxxabi/test/forced_unwind3.pass.cpp
@@ -0,0 +1,79 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Let's run ForcedUnwind until it reaches end of the stack, this test simulates
+// what pthread_cancel does.
+
+// UNSUPPORTED: c++03
+// UNSUPPORTED: libcxxabi-no-threads
+// UNSUPPORTED: no-exceptions
+
+#include <assert.h>
+#include <exception>
+#include <stdlib.h>
+#include <string.h>
+#include <unwind.h>
+#include <thread>
+#include <tuple>
+#include <__cxxabi_config.h>
+
+// TODO: dump version back to 14 once clang is updated on the CI.
+#if defined(_LIBCXXABI_ARM_EHABI) && defined(__clang__) && __clang_major__ < 15
+// _Unwind_ForcedUnwind is not available or broken before version 14.
+int main(int, char**) { return 0; }
+
+#else
+static bool destructorCalled = false;
+
+struct myClass {
+ myClass() {}
+ ~myClass() {
+ assert(destructorCalled == false);
+ destructorCalled = true;
+ };
+};
+
+template <typename T>
+struct Stop;
+
+template <typename R, typename... Args>
+struct Stop<R (*)(Args...)> {
+ // The third argument of _Unwind_Stop_Fn is uint64_t in Itanium C++ ABI/LLVM
+ // libunwind while _Unwind_Exception_Class in libgcc.
+ typedef typename std::tuple_element<2, std::tuple<Args...>>::type type;
+
+ static _Unwind_Reason_Code stop(int, _Unwind_Action actions, type, struct _Unwind_Exception*, struct _Unwind_Context*,
+ void*) {
+ if (actions & _UA_END_OF_STACK) {
+ assert(destructorCalled == true);
+ exit(0);
+ }
+ return _URC_NO_REASON;
+ }
+};
+
+static void forced_unwind() {
+ _Unwind_Exception* exc = new _Unwind_Exception;
+ memset(&exc->exception_class, 0, sizeof(exc->exception_class));
+ exc->exception_cleanup = 0;
+ _Unwind_ForcedUnwind(exc, Stop<_Unwind_Stop_Fn>::stop, 0);
+ abort();
+}
+
+__attribute__((__noinline__)) static void test() {
+ myClass c{};
+ forced_unwind();
+ abort();
+}
+
+int main(int, char**) {
+ std::thread t{test};
+ t.join();
+ return -1;
+}
+#endif
Index: libcxxabi/src/cxa_personality.cpp
===================================================================
--- libcxxabi/src/cxa_personality.cpp
+++ libcxxabi/src/cxa_personality.cpp
@@ -1004,9 +1004,14 @@
static _Unwind_Reason_Code continue_unwind(_Unwind_Exception* unwind_exception,
_Unwind_Context* context)
{
- if (__gnu_unwind_frame(unwind_exception, context) != _URC_OK)
- return _URC_FAILURE;
+ switch (__gnu_unwind_frame(unwind_exception, context)) {
+ case _URC_OK:
return _URC_CONTINUE_UNWIND;
+ case _URC_END_OF_STACK:
+ return _URC_END_OF_STACK;
+ default:
+ return _URC_FAILURE;
+ }
}
// ARM register names
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits