Page MenuHomePhabricator

[Android] Use -l:libunwind.a with --rtlib=compiler-rt
ClosedPublic

Authored by rprichard on Feb 10 2021, 3:03 AM.

Details

Summary

On Android, the unwinder isn't part of the C++ STL and isn't (in older
versions) exported from libc.so. Instead, the driver links the static
unwinder archive implicitly. Currently, the Android NDK implicitly
links libgcc.a to provide both builtins and the unwinder.

To support switching to compiler-rt builtins and libunwind, make
--rtlib=compiler-rt behave the same way on Android, and implicitly pass
-l:libunwind.a to the linker.

Adjust the -ldl logic. For the Android NDK, the unwinder (whether
libgcc.a or libunwind.a) is linked statically and calls a function in
the dynamic loader for finding unwind tables (e.g. dl_iterate_phdr).
On Android, this function is in libc.a for static executables and
libdl.so otherwise, so -ldl is needed. (glibc doesn't need -ldl because
its libc.so exports dl_iterate_phdr.)

Diff Detail

Event Timeline

rprichard created this revision.Feb 10 2021, 3:03 AM
rprichard requested review of this revision.Feb 10 2021, 3:03 AM
Herald added a project: Restricted Project. · View Herald TranscriptFeb 10 2021, 3:03 AM
rprichard added reviewers: srhines, danalbert, pcc.
rprichard added a subscriber: Restricted Project.
danalbert accepted this revision.Feb 10 2021, 12:23 PM
This revision is now accepted and ready to land.Feb 10 2021, 12:23 PM

For reference, I know of four ways that LLVM's libunwind is currently linked into programs:

  • Fuchsia/Windows (i.e. Clang's default behavior): it's part of libc++, e.g.:
    • Fuchsia:
      • fuchsia/prebuilt/third_party/clang/linux-x64/lib/x86_64-unknown-fuchsia/c++/libc++.so is INPUT(libc++.so.2 -lunwind -lc++abi).
      • fuchsia/prebuilt/third_party/clang/linux-x64/lib/x86_64-unknown-fuchsia/c++/libc++.a is an archive that contains the libunwind object files.
    • In https://github.com/mstorsjo/llvm-mingw/releases/tag/20201020:
      • llvm-mingw\x86_64-w64-mingw32\bin\libc++.dll uses _Unwind_Resume from libunwind.dll
      • llvm-mingw\x86_64-w64-mingw32\lib\libc++.dll.a also seems to import _Unwind_Resume from libunwind.dll
      • llvm-mingw\x86_64-w64-mingw32\lib\libc++.a has the libunwind object files in it
  • FreeBSD: libclang_rt.builtins and libunwind are repackaged into libraries that look like libgcc, linked implicitly.
  • Darwin: it's part of libSystem, linked implicitly.
  • crosstool in google3: I think this build system is passing --unwindlib=libunwind to the driver.

The Android team's LLVM build is used to target several OS's: host/glibc Linux, Windows, Darwin, and Android. At some point, we'd also like Android NDK to rely on the unwinder exported from libc.so (when the API level is high enough), which prevents us from using Clang's CLANG_DEFAULT_UNWINDLIB config setting.

Even for C programs, the unwinder has at least a couple of uses I know of:

  • _Unwind_Backtrace
  • __attribute__((cleanup)) with -fexceptions

I don't really know how important these use cases are, or whether there are other important use cases I'm not thinking of. I'd prefer to keep linking the unwinder implicitly.

See D57128 and D59109.

I think the Android team is happy with this driver change, though, so I expect I'll push it next week.

This revision was landed with ongoing or failed builds.Feb 25 2021, 3:40 PM
This revision was automatically updated to reflect the committed changes.

With NDK r22, I only see libunwind.a for armv7. Will it be provided for other architectures in future NDK versions?

With NDK r22, I only see libunwind.a for armv7. Will it be provided for other architectures in future NDK versions?

NDK r23 should have a libunwind.a for all architectures. This change isn't in the r23 beta 2 that was just released, but it is in the current NDK canary build at https://ci.android.com/builds/branches/aosp-master-ndk/grid. (e.g. build 7220482).

With NDK r22, I only see libunwind.a for armv7. Will it be provided for other architectures in future NDK versions?

NDK r23 should have a libunwind.a for all architectures. This change isn't in the r23 beta 2 that was just released, but it is in the current NDK canary build at https://ci.android.com/builds/branches/aosp-master-ndk/grid. (e.g. build 7220482).

Got it, thanks.

Is there a public repository for viewing the libunwind source state that the NDK r23 libunwind is built from? I have the AOSP source tree checked out (following the instructions in https://source.android.com/setup/build/downloading) on the llvm-toolchain manifest branch. toolchain/llvm-project inside that checkout (https://android.googlesource.com/toolchain/llvm-project) has a branch for ndk-release-r23, but the merge base of that branch and upstream LLVM main is from April 29 2020, and I don't see many newer changes to libunwind after that, so I wasn't sure I was looking at the right place. I know you've done a bunch more libunwind work since then (e.g. D87750, D87881, and D90898), so I was curious if those were gonna be part of r23's libunwind.

srhines added a comment.EditedMar 19 2021, 7:08 PM

With NDK r22, I only see libunwind.a for armv7. Will it be provided for other architectures in future NDK versions?

NDK r23 should have a libunwind.a for all architectures. This change isn't in the r23 beta 2 that was just released, but it is in the current NDK canary build at https://ci.android.com/builds/branches/aosp-master-ndk/grid. (e.g. build 7220482).

Got it, thanks.

Is there a public repository for viewing the libunwind source state that the NDK r23 libunwind is built from? I have the AOSP source tree checked out (following the instructions in https://source.android.com/setup/build/downloading) on the llvm-toolchain manifest branch. toolchain/llvm-project inside that checkout (https://android.googlesource.com/toolchain/llvm-project) has a branch for ndk-release-r23, but the merge base of that branch and upstream LLVM main is from April 29 2020, and I don't see many newer changes to libunwind after that, so I wasn't sure I was looking at the right place. I know you've done a bunch more libunwind work since then (e.g. D87750, D87881, and D90898), so I was curious if those were gonna be part of r23's libunwind.

So libunwind is now produced as a prebuilt with the rest of the toolchain build, and not built from that copy of toolchain/llvm_project from the NDK packaging/release branch. Thus if you want to rebuild/examine the sources, you need to look at the toolchain that was included for NDK r23, which is clang-r399163b (from https://android.googlesource.com/platform/ndk/+/refs/tags/ndk-r23-beta2/ndk/toolchains.py#25). Given that, you can get the manifest for the toolchain directly here. You can use that manifest to check out the exact sources that were used to build everything (following instructions from here).

^ PROCESS is correct, but I picked the wrong version (not beta2). I'll update and post a better reply in a few minutes.

With NDK r22, I only see libunwind.a for armv7. Will it be provided for other architectures in future NDK versions?

NDK r23 should have a libunwind.a for all architectures. This change isn't in the r23 beta 2 that was just released, but it is in the current NDK canary build at https://ci.android.com/builds/branches/aosp-master-ndk/grid. (e.g. build 7220482).

Got it, thanks.

Is there a public repository for viewing the libunwind source state that the NDK r23 libunwind is built from? I have the AOSP source tree checked out (following the instructions in https://source.android.com/setup/build/downloading) on the llvm-toolchain manifest branch. toolchain/llvm-project inside that checkout (https://android.googlesource.com/toolchain/llvm-project) has a branch for ndk-release-r23, but the merge base of that branch and upstream LLVM main is from April 29 2020, and I don't see many newer changes to libunwind after that, so I wasn't sure I was looking at the right place. I know you've done a bunch more libunwind work since then (e.g. D87750, D87881, and D90898), so I was curious if those were gonna be part of r23's libunwind.

So libunwind is now produced as a prebuilt with the rest of the toolchain build, and not built from that copy of toolchain/llvm_project from the NDK packaging/release branch. Thus if you want to rebuild/examine the sources, you need to look at the toolchain that was included for NDK r23, which is clang-r399163b (from https://android.googlesource.com/platform/ndk/+/refs/tags/ndk-r23-beta2/ndk/toolchains.py#25). Given that, you can get the manifest for the toolchain directly here. You can use that manifest to check out the exact sources that were used to build everything (following instructions from here).

^ PROCESS is correct, but I picked the wrong version (not beta2). I'll update and post a better reply in a few minutes.

It is actually using clang-r416183 from toolchains.py. From there, you can go to the manifest for building those prebuilts. This line shows you the SHA for the toolchain/llvm-project used to build the prebuilts. Finally, you can look here to see what was merged. Note that there's a typo for the revision number in the commit message, but the upstream LLVM SHA mentioned there is correct. Here is where this toolchain was built in case that is useful/interesting.

Got it, thanks for all the info!

It is actually using clang-r416183 from toolchains.py. From there, you can go to the manifest for building those prebuilts. This line shows you the SHA for the toolchain/llvm-project used to build the prebuilts. Finally, you can look here to see what was merged. Note that there's a typo for the revision number in the commit message, but the upstream LLVM SHA mentioned there is correct. Here is where this toolchain was built in case that is useful/interesting.

Also: that manifest also links to the toolchain/llvm_android git repository, which has a Python-based build system and a series of patches (mostly cherry-picks) applied to the baseline llvm-project source.