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

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.)

Differential Revision: https://reviews.llvm.org/D96403
This commit is contained in:
Ryan Prichard 2021-02-10 01:25:58 -08:00
parent c88fedef2a
commit 91f8aacc04
2 changed files with 25 additions and 17 deletions

View File

@ -929,9 +929,12 @@ ToolChain::UnwindLibType ToolChain::GetUnwindLibType(
unwindLibType = ToolChain::UNW_None;
else if (LibName == "platform" || LibName == "") {
ToolChain::RuntimeLibType RtLibType = GetRuntimeLibType(Args);
if (RtLibType == ToolChain::RLT_CompilerRT)
unwindLibType = ToolChain::UNW_None;
else if (RtLibType == ToolChain::RLT_Libgcc)
if (RtLibType == ToolChain::RLT_CompilerRT) {
if (getTriple().isAndroid())
unwindLibType = ToolChain::UNW_CompilerRT;
else
unwindLibType = ToolChain::UNW_None;
} else if (RtLibType == ToolChain::RLT_Libgcc)
unwindLibType = ToolChain::UNW_Libgcc;
} else if (LibName == "libunwind") {
if (GetRuntimeLibType(Args) == RLT_Libgcc)

View File

@ -1366,11 +1366,17 @@ bool tools::isObjCAutoRefCount(const ArgList &Args) {
enum class LibGccType { UnspecifiedLibGcc, StaticLibGcc, SharedLibGcc };
static LibGccType getLibGccType(const Driver &D, const ArgList &Args) {
static LibGccType getLibGccType(const ToolChain &TC, const Driver &D,
const ArgList &Args) {
if (Args.hasArg(options::OPT_static_libgcc) ||
Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_static_pie))
return LibGccType::StaticLibGcc;
if (Args.hasArg(options::OPT_shared_libgcc) || D.CCCIsCXX())
if (Args.hasArg(options::OPT_shared_libgcc))
return LibGccType::SharedLibGcc;
// The Android NDK only provides libunwind.a, not libunwind.so.
if (TC.getTriple().isAndroid())
return LibGccType::StaticLibGcc;
if (D.CCCIsCXX())
return LibGccType::SharedLibGcc;
return LibGccType::UnspecifiedLibGcc;
}
@ -1392,12 +1398,12 @@ static void AddUnwindLibrary(const ToolChain &TC, const Driver &D,
ArgStringList &CmdArgs, const ArgList &Args) {
ToolChain::UnwindLibType UNW = TC.GetUnwindLibType(Args);
// Targets that don't use unwind libraries.
if (TC.getTriple().isAndroid() || TC.getTriple().isOSIAMCU() ||
TC.getTriple().isOSBinFormatWasm() ||
if ((TC.getTriple().isAndroid() && UNW == ToolChain::UNW_Libgcc) ||
TC.getTriple().isOSIAMCU() || TC.getTriple().isOSBinFormatWasm() ||
UNW == ToolChain::UNW_None)
return;
LibGccType LGT = getLibGccType(D, Args);
LibGccType LGT = getLibGccType(TC, D, Args);
bool AsNeeded = LGT == LibGccType::UnspecifiedLibGcc &&
!TC.getTriple().isAndroid() && !TC.getTriple().isOSCygMing();
if (AsNeeded)
@ -1434,20 +1440,12 @@ static void AddUnwindLibrary(const ToolChain &TC, const Driver &D,
static void AddLibgcc(const ToolChain &TC, const Driver &D,
ArgStringList &CmdArgs, const ArgList &Args) {
LibGccType LGT = getLibGccType(D, Args);
LibGccType LGT = getLibGccType(TC, D, Args);
if (LGT != LibGccType::SharedLibGcc)
CmdArgs.push_back("-lgcc");
AddUnwindLibrary(TC, D, CmdArgs, Args);
if (LGT == LibGccType::SharedLibGcc)
CmdArgs.push_back("-lgcc");
// According to Android ABI, we have to link with libdl if we are
// linking with non-static libgcc.
//
// NOTE: This fixes a link error on Android MIPS as well. The non-static
// libgcc for MIPS relies on _Unwind_Find_FDE and dl_iterate_phdr from libdl.
if (TC.getTriple().isAndroid() && LGT != LibGccType::StaticLibGcc)
CmdArgs.push_back("-ldl");
}
void tools::AddRunTimeLibs(const ToolChain &TC, const Driver &D,
@ -1473,6 +1471,13 @@ void tools::AddRunTimeLibs(const ToolChain &TC, const Driver &D,
AddLibgcc(TC, D, CmdArgs, Args);
break;
}
// On Android, the unwinder uses dl_iterate_phdr (or one of
// dl_unwind_find_exidx/__gnu_Unwind_Find_exidx on arm32) from libdl.so. For
// statically-linked executables, these functions come from libc.a instead.
if (TC.getTriple().isAndroid() && !Args.hasArg(options::OPT_static) &&
!Args.hasArg(options::OPT_static_pie))
CmdArgs.push_back("-ldl");
}
SmallString<128> tools::getStatsFileName(const llvm::opt::ArgList &Args,