[libunwind] [libunwind][AIX] Remove weak declaration "__xlcxx_personality_v0" (PR #112436)

Xing Xue via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 16 11:28:54 PDT 2024


https://github.com/xingxue-ibm updated https://github.com/llvm/llvm-project/pull/112436

>From edabcb3b43800c3e12a55325a786600064ccde10 Mon Sep 17 00:00:00 2001
From: Xing Xue <xingxue at outlook.com>
Date: Tue, 15 Oct 2024 16:21:29 -0400
Subject: [PATCH 1/3] Remove weak definition "__xlcxx_personality_v0".

---
 libunwind/src/UnwindCursor.hpp | 52 ++++++++++++++--------------------
 1 file changed, 22 insertions(+), 30 deletions(-)

diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp
index ce6dced535e781..8869be5236b1e6 100644
--- a/libunwind/src/UnwindCursor.hpp
+++ b/libunwind/src/UnwindCursor.hpp
@@ -2033,7 +2033,6 @@ typedef _Unwind_Reason_Code __xlcxx_personality_v0_t(int, _Unwind_Action,
                                                      uint64_t,
                                                      _Unwind_Exception *,
                                                      struct _Unwind_Context *);
-__attribute__((__weak__)) __xlcxx_personality_v0_t __xlcxx_personality_v0;
 }
 
 static __xlcxx_personality_v0_t *xlcPersonalityV0;
@@ -2126,42 +2125,35 @@ bool UnwindCursor<A, R>::getInfoFromTBTable(pint_t pc, R &registers) {
     // function __xlcxx_personality_v0(), which is the personality for the state
     // table and is exported from libc++abi, is directly assigned as the
     // handler here. When a legacy XLC++ frame is encountered, the symbol
-    // is resolved dynamically using dlopen() to avoid hard dependency from
-    // libunwind on libc++abi.
+    // is resolved dynamically using dlopen() to avoid a hard dependency of
+    // libunwind on libc++abi in cases such as non-C++ applications.
 
     // Resolve the function pointer to the state table personality if it has
-    // not already.
+    // not already done.
     if (xlcPersonalityV0 == NULL) {
       xlcPersonalityV0InitLock.lock();
       if (xlcPersonalityV0 == NULL) {
-        // If libc++abi is statically linked in, symbol __xlcxx_personality_v0
-        // has been resolved at the link time.
-        xlcPersonalityV0 = &__xlcxx_personality_v0;
+        // Resolve __xlcxx_personality_v0 using dlopen().
+        const char libcxxabi[] = "libc++abi.a(libc++abi.so.1)";
+        void *libHandle;
+        // The AIX dlopen() sets errno to 0 when it is successful, which
+        // clobbers the value of errno from the user code. This is an AIX
+        // bug because according to POSIX it should not set errno to 0. To
+        // workaround before AIX fixes the bug, errno is saved and restored.
+        int saveErrno = errno;
+        libHandle = dlopen(libcxxabi, RTLD_MEMBER | RTLD_NOW);
+        if (libHandle == NULL) {
+          _LIBUNWIND_TRACE_UNWINDING("dlopen() failed with errno=%d\n",
+                                     errno);
+          assert(0 && "dlopen() failed");
+        }
+        xlcPersonalityV0 = reinterpret_cast<__xlcxx_personality_v0_t *>(
+            dlsym(libHandle, "__xlcxx_personality_v0"));
         if (xlcPersonalityV0 == NULL) {
-          // libc++abi is dynamically linked. Resolve __xlcxx_personality_v0
-          // using dlopen().
-          const char libcxxabi[] = "libc++abi.a(libc++abi.so.1)";
-          void *libHandle;
-          // The AIX dlopen() sets errno to 0 when it is successful, which
-          // clobbers the value of errno from the user code. This is an AIX
-          // bug because according to POSIX it should not set errno to 0. To
-          // workaround before AIX fixes the bug, errno is saved and restored.
-          int saveErrno = errno;
-          libHandle = dlopen(libcxxabi, RTLD_MEMBER | RTLD_NOW);
-          if (libHandle == NULL) {
-            _LIBUNWIND_TRACE_UNWINDING("dlopen() failed with errno=%d\n",
-                                       errno);
-            assert(0 && "dlopen() failed");
-          }
-          xlcPersonalityV0 = reinterpret_cast<__xlcxx_personality_v0_t *>(
-              dlsym(libHandle, "__xlcxx_personality_v0"));
-          if (xlcPersonalityV0 == NULL) {
-            _LIBUNWIND_TRACE_UNWINDING("dlsym() failed with errno=%d\n", errno);
-            assert(0 && "dlsym() failed");
-          }
-          dlclose(libHandle);
-          errno = saveErrno;
+          _LIBUNWIND_TRACE_UNWINDING("dlsym() failed with errno=%d\n", errno);
+          assert(0 && "dlsym() failed");
         }
+        errno = saveErrno;
       }
       xlcPersonalityV0InitLock.unlock();
     }

>From b85f82b879da7dd30532b315eb1ea7278e45b132 Mon Sep 17 00:00:00 2001
From: Xing Xue <xingxue at outlook.com>
Date: Tue, 15 Oct 2024 16:57:44 -0400
Subject: [PATCH 2/3] Fix formatting.

---
 libunwind/src/UnwindCursor.hpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp
index 8869be5236b1e6..60079bd9cd18a2 100644
--- a/libunwind/src/UnwindCursor.hpp
+++ b/libunwind/src/UnwindCursor.hpp
@@ -2143,8 +2143,7 @@ bool UnwindCursor<A, R>::getInfoFromTBTable(pint_t pc, R &registers) {
         int saveErrno = errno;
         libHandle = dlopen(libcxxabi, RTLD_MEMBER | RTLD_NOW);
         if (libHandle == NULL) {
-          _LIBUNWIND_TRACE_UNWINDING("dlopen() failed with errno=%d\n",
-                                     errno);
+          _LIBUNWIND_TRACE_UNWINDING("dlopen() failed with errno=%d\n", errno);
           assert(0 && "dlopen() failed");
         }
         xlcPersonalityV0 = reinterpret_cast<__xlcxx_personality_v0_t *>(

>From 44000d5a80a61efbddd5dc6147dd4321586b6d6a Mon Sep 17 00:00:00 2001
From: Xing Xue <xingxue at outlook.com>
Date: Wed, 16 Oct 2024 13:26:28 -0400
Subject: [PATCH 3/3] Addressed comments: - fix comments - add a LIT test case
 - will put driver-by fix to remove dlclose() in a separate PR

---
 libunwind/src/UnwindCursor.hpp           |  5 +++--
 libunwind/test/aix_runtime_link.pass.cpp | 20 ++++++++++++++++++++
 2 files changed, 23 insertions(+), 2 deletions(-)
 create mode 100644 libunwind/test/aix_runtime_link.pass.cpp

diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp
index 60079bd9cd18a2..2a3aba28fb6ca5 100644
--- a/libunwind/src/UnwindCursor.hpp
+++ b/libunwind/src/UnwindCursor.hpp
@@ -2129,12 +2129,12 @@ bool UnwindCursor<A, R>::getInfoFromTBTable(pint_t pc, R &registers) {
     // libunwind on libc++abi in cases such as non-C++ applications.
 
     // Resolve the function pointer to the state table personality if it has
-    // not already done.
+    // not already been done.
     if (xlcPersonalityV0 == NULL) {
       xlcPersonalityV0InitLock.lock();
       if (xlcPersonalityV0 == NULL) {
         // Resolve __xlcxx_personality_v0 using dlopen().
-        const char libcxxabi[] = "libc++abi.a(libc++abi.so.1)";
+        const char *libcxxabi = "libc++abi.a(libc++abi.so.1)";
         void *libHandle;
         // The AIX dlopen() sets errno to 0 when it is successful, which
         // clobbers the value of errno from the user code. This is an AIX
@@ -2152,6 +2152,7 @@ bool UnwindCursor<A, R>::getInfoFromTBTable(pint_t pc, R &registers) {
           _LIBUNWIND_TRACE_UNWINDING("dlsym() failed with errno=%d\n", errno);
           assert(0 && "dlsym() failed");
         }
+        dlclose(libHandle);
         errno = saveErrno;
       }
       xlcPersonalityV0InitLock.unlock();
diff --git a/libunwind/test/aix_runtime_link.pass.cpp b/libunwind/test/aix_runtime_link.pass.cpp
new file mode 100644
index 00000000000000..deb192c07981eb
--- /dev/null
+++ b/libunwind/test/aix_runtime_link.pass.cpp
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// Test that libunwind loads successfully independently of libc++abi with
+// runtime linking on AIX.
+
+// REQUIRES: target={{.+}}-aix{{.*}}
+// ADDITIONAL_COMPILE_FLAGS: -Wl,-brtl
+
+#include <unwind.h>
+extern "C" int printf(const char *, ...);
+int main(void) {
+  void *fp = (void *)&_Unwind_Backtrace;
+  printf("%p\n", fp);
+}



More information about the cfe-commits mailing list