Skip to content

Commit 2ef24e0

Browse files
authored
[libunwind][AIX] Remove weak declaration "__xlcxx_personality_v0" (#112436)
`__xlcxx_personality_v0` is the personality routine in `libc++abi` for the EH of applications generated by the legacy IBM C++ compiler. Since the EH info generated by the legacy compiler does not provide the location of the personality routine, this routine is hard-coded as the handler for legacy EH in the unwinder. The symbol is resolved dynamically using `dlopen()` to avoid a hard dependency of `libunwind` on `libc++abi` for cases such as non-C++ applications. The weak declaration of `__xlcxx_personality_v0` was originally intended to bypass `dlopen()` if the C++ application generated by the legacy compiler is statically linked with the new LLVM C++ compiler. Unfortunately, this causes problems with runtime linking for Clang-compiled code using the unwinder that does not link with `libc++abi`. On the other hand, the C++ runtime libraries shipped for AIX are actually stripped and statically linking is not supported. So, we can fix the problem by removing the `__xlcxx_personality_v0` weak declaration. Besides, `dlopen()` would work as long as the libc++abi shared library is available.
1 parent 1a60905 commit 2ef24e0

File tree

2 files changed

+42
-30
lines changed

2 files changed

+42
-30
lines changed

libunwind/src/UnwindCursor.hpp

Lines changed: 22 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2033,7 +2033,6 @@ typedef _Unwind_Reason_Code __xlcxx_personality_v0_t(int, _Unwind_Action,
20332033
uint64_t,
20342034
_Unwind_Exception *,
20352035
struct _Unwind_Context *);
2036-
__attribute__((__weak__)) __xlcxx_personality_v0_t __xlcxx_personality_v0;
20372036
}
20382037

20392038
static __xlcxx_personality_v0_t *xlcPersonalityV0;
@@ -2126,42 +2125,35 @@ bool UnwindCursor<A, R>::getInfoFromTBTable(pint_t pc, R &registers) {
21262125
// function __xlcxx_personality_v0(), which is the personality for the state
21272126
// table and is exported from libc++abi, is directly assigned as the
21282127
// handler here. When a legacy XLC++ frame is encountered, the symbol
2129-
// is resolved dynamically using dlopen() to avoid hard dependency from
2130-
// libunwind on libc++abi.
2128+
// is resolved dynamically using dlopen() to avoid a hard dependency of
2129+
// libunwind on libc++abi in cases such as non-C++ applications.
21312130

21322131
// Resolve the function pointer to the state table personality if it has
2133-
// not already.
2132+
// not already been done.
21342133
if (xlcPersonalityV0 == NULL) {
21352134
xlcPersonalityV0InitLock.lock();
21362135
if (xlcPersonalityV0 == NULL) {
2137-
// If libc++abi is statically linked in, symbol __xlcxx_personality_v0
2138-
// has been resolved at the link time.
2139-
xlcPersonalityV0 = &__xlcxx_personality_v0;
2136+
// Resolve __xlcxx_personality_v0 using dlopen().
2137+
const char *libcxxabi = "libc++abi.a(libc++abi.so.1)";
2138+
void *libHandle;
2139+
// The AIX dlopen() sets errno to 0 when it is successful, which
2140+
// clobbers the value of errno from the user code. This is an AIX
2141+
// bug because according to POSIX it should not set errno to 0. To
2142+
// workaround before AIX fixes the bug, errno is saved and restored.
2143+
int saveErrno = errno;
2144+
libHandle = dlopen(libcxxabi, RTLD_MEMBER | RTLD_NOW);
2145+
if (libHandle == NULL) {
2146+
_LIBUNWIND_TRACE_UNWINDING("dlopen() failed with errno=%d\n", errno);
2147+
assert(0 && "dlopen() failed");
2148+
}
2149+
xlcPersonalityV0 = reinterpret_cast<__xlcxx_personality_v0_t *>(
2150+
dlsym(libHandle, "__xlcxx_personality_v0"));
21402151
if (xlcPersonalityV0 == NULL) {
2141-
// libc++abi is dynamically linked. Resolve __xlcxx_personality_v0
2142-
// using dlopen().
2143-
const char libcxxabi[] = "libc++abi.a(libc++abi.so.1)";
2144-
void *libHandle;
2145-
// The AIX dlopen() sets errno to 0 when it is successful, which
2146-
// clobbers the value of errno from the user code. This is an AIX
2147-
// bug because according to POSIX it should not set errno to 0. To
2148-
// workaround before AIX fixes the bug, errno is saved and restored.
2149-
int saveErrno = errno;
2150-
libHandle = dlopen(libcxxabi, RTLD_MEMBER | RTLD_NOW);
2151-
if (libHandle == NULL) {
2152-
_LIBUNWIND_TRACE_UNWINDING("dlopen() failed with errno=%d\n",
2153-
errno);
2154-
assert(0 && "dlopen() failed");
2155-
}
2156-
xlcPersonalityV0 = reinterpret_cast<__xlcxx_personality_v0_t *>(
2157-
dlsym(libHandle, "__xlcxx_personality_v0"));
2158-
if (xlcPersonalityV0 == NULL) {
2159-
_LIBUNWIND_TRACE_UNWINDING("dlsym() failed with errno=%d\n", errno);
2160-
assert(0 && "dlsym() failed");
2161-
}
2162-
dlclose(libHandle);
2163-
errno = saveErrno;
2152+
_LIBUNWIND_TRACE_UNWINDING("dlsym() failed with errno=%d\n", errno);
2153+
assert(0 && "dlsym() failed");
21642154
}
2155+
dlclose(libHandle);
2156+
errno = saveErrno;
21652157
}
21662158
xlcPersonalityV0InitLock.unlock();
21672159
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// Test that libunwind loads successfully independently of libc++abi with
10+
// runtime linking on AIX.
11+
12+
// REQUIRES: target={{.+}}-aix{{.*}}
13+
// ADDITIONAL_COMPILE_FLAGS: -Wl,-brtl
14+
15+
#include <unwind.h>
16+
extern "C" int printf(const char *, ...);
17+
int main(void) {
18+
void *fp = (void *)&_Unwind_Backtrace;
19+
printf("%p\n", fp);
20+
}

0 commit comments

Comments
 (0)