监视 SDK 下的未定义符号"__Unwind_SjLj_Unregister"
Undefined symbol "__Unwind_SjLj_Unregister" under Watch SDK
我们在 Travis 上遇到 Apple WatchOS 构建失败的C++库。其他配置,如iPhone,iPhoneSimulator和AppleTV都可以。
库编译正常,但链接失败。典型的编译调用是:
clang++ -DNDEBUG -g2 -O3 -fPIC -pipe -Wall -arch armv7 -stdlib=libc++ -isysroot
/Applications/Xcode.app/Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs/WatchOS3.1.sdk
-c cryptlib.cpp
clang++ -DNDEBUG -g2 -O3 -fPIC -pipe -Wall -arch armv7 -stdlib=libc++ -isysroot
/Applications/Xcode.app/Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs/WatchOS3.1.sdk
-c cpu.cpp
clang++ -DNDEBUG -g2 -O3 -fPIC -pipe -Wall -arch armv7 -stdlib=libc++ -isysroot
/Applications/Xcode.app/Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs/WatchOS3.1.sdk
-c integer.cpp
...
编译后有很多链接器错误,如下所示。我们不确定这些是误报,还是错过了必要的选项或库。
我尝试搜索 Apple Developer ,但无法找到特定于 Watch 版本的信息。我发现了一些类似的问题,例如未定义的符号编译iPhone的增强上下文,但它们没有得到解答(并且是错误的平台(。
我有一台较旧的MacBook进行测试,但它运行的是OS X 10.9,并且有Xcode 6。它太老了,无法尝试解决这个问题。例如,它没有 WatchOS,无法解码缺少的符号名称:
$ echo __Unwind_SjLj_Register | c++filt
__Unwind_SjLj_Register
测试此配置时是否会出现链接错误?如果不是,那么架构是否正确?也许,我们缺少哪些选项或"手表和电视"库?
我最近在 Clang 源代码中发现了这个,ToolChain.cpp
:
bool Darwin::UseSjLjExceptions(const ArgList &Args) const {
// Darwin uses SjLj exceptions on ARM.
if (getTriple().getArch() != llvm::Triple::arm &&
getTriple().getArch() != llvm::Triple::thumb)
return false;
// Only watchOS uses the new DWARF/Compact unwinding method.
llvm::Triple Triple(ComputeLLVMTriple(Args));
return !Triple.isWatchABI();
}
这是链接的样子。我们通过编译器驱动它,我们使用相同的CXXFLAGS
.
clang++ -o cryptest.exe -DNDEBUG -g2 -O3 -fPIC -pipe -Wall -arch armv7 -isysroot
/Applications/Xcode.app/Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs/WatchOS3.1.sdk
-stdlib=libc++ adhoc.o test.o bench1.o bench2.o validat0.o validat1.o validat2.o validat3.o
datatest.o regtest1.o regtest2.o regtest3.o fipsalgt.o dlltest.o ./libcryptopp.a
Undefined symbols for architecture armv7:
"__Unwind_SjLj_Register", referenced from:
CryptoPP::CipherModeFinalTemplate_CipherHolder<CryptoPP::BlockCipherFinal<(CryptoPP::CipherDir)0, CryptoPP::Rijndael::Enc>, CryptoPP::ConcretePolicyHolder<CryptoPP::Empty, CryptoPP::AdditiveCipherTemplate<CryptoPP::AbstractPolicyHolder<CryptoPP::AdditiveCipherAbstractPolicy, CryptoPP::OFB_ModePolicy> >, CryptoPP::AdditiveCipherAbstractPolicy> >::~CipherModeFinalTemplate_CipherHolder() in test.o
CryptoPP::Test::scoped_main(int, char**) in test.o
std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > CryptoPP::IntToString<long>(long, unsigned int) in test.o
std::__1::basic_istream<char, std::__1::char_traits<char> >& std::__1::operator>><char, std::__1::char_traits<char> >(std::__1::basic_istream<char, std::__1::char_traits<char> >&, char*) in test.o
std::__1::basic_istream<char, std::__1::char_traits<char> >& std::__1::ws<char, std::__1::char_traits<char> >(std::__1::basic_istream<char, std::__1::char_traits<char> >&) in test.o
CryptoPP::Test::GenerateRSAKey(unsigned int, char const*, char const*, char const*) in test.o
CryptoPP::Test::RSASignFile(char const*, char const*, char const*) in test.o
...
"__Unwind_SjLj_Resume", referenced from:
CryptoPP::CipherModeFinalTemplate_CipherHolder<CryptoPP::BlockCipherFinal<(CryptoPP::CipherDir)0, CryptoPP::Rijndael::Enc>, CryptoPP::ConcretePolicyHolder<CryptoPP::Empty, CryptoPP::AdditiveCipherTemplate<CryptoPP::AbstractPolicyHolder<CryptoPP::AdditiveCipherAbstractPolicy, CryptoPP::OFB_ModePolicy> >, CryptoPP::AdditiveCipherAbstractPolicy> >::~CipherModeFinalTemplate_CipherHolder() in test.o
CryptoPP::Test::scoped_main(int, char**) in test.o
std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > CryptoPP::IntToString<long>(long, unsigned int) in test.o
std::__1::basic_istream<char, std::__1::char_traits<char> >& std::__1::operator>><char, std::__1::char_traits<char> >(std::__1::basic_istream<char, std::__1::char_traits<char> >&, char*) in test.o
std::__1::basic_istream<char, std::__1::char_traits<char> >& std::__1::ws<char, std::__1::char_traits<char> >(std::__1::basic_istream<char, std::__1::char_traits<char> >&) in test.o
CryptoPP::Test::GenerateRSAKey(unsigned int, char const*, char const*, char const*) in test.o
CryptoPP::Test::RSASignFile(char const*, char const*, char const*) in test.o
...
我认为这可能已由 LLVM 在 2017 年 9 月修复 SJLJ 异常处理时修复,当在非默认平台上手动选择时。
我最近也从一个补丁中遇到了这个问题,这可能会解决问题。cfe/docs/ClangCommandLineReference.rst
:
.. option:: -fsjlj-exceptions
Use SjLj style exceptions