监视 SDK 下的未定义符号"__Unwind_SjLj_Unregister"

Undefined symbol "__Unwind_SjLj_Unregister" under Watch SDK

本文关键字:Unwind SjLj Unregister 符号 SDK 未定义 监视      更新时间:2023-10-16

我们在 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