Undefined symbols in Crypto++/iOS 64-bit project

拥有回忆 提交于 2019-11-29 16:27:59
jww
Undefined symbols for architecture arm64: "CryptoPP::BufferedTransformation::ChannelFlush(std::string const&, bool, int, bool)", referenced from:

 vtable for CryptoPP::SimpleProxyFilter in MYCLASSBBB.o
 vtable for CryptoPP::Bufferless<CryptoPP::Filter> in MYCLASSBBB.o

I think you are not using libc++, which is LLVM's C++ standard library. I think that because I don't see a -stdlib=libc++ (but I don't recall if that's passed to ld directly).

The symbol is defined in the github's prebuilt cryptopp (that's my github, btw). Here's how to verify.

First, extract the arm64 library from the fat library:

$ xcrun -sdk iphoneos lipo libcryptopp.a -thin arm64 -output libcryptopp-arm64.a
$ ls
libcryptopp-arm64.a libcryptopp.a

Next, use nm to dump global symbols, and use c++filt to demangle:

$ nm -g libcryptopp-arm64.a | c++filt | grep BufferedTransformation::ChannelFlush | grep " T "
0000000000002110 T CryptoPP::BufferedTransformation::ChannelFlush(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool, int, bool)

The capitol T means you are searching for symbols that are defined and exported. Lower t means its defined but not exported - i.e., private. Capitol U means its undefined.

The __1 is what libc++ (LLVM) uses to differentiate from libstdc++ (GNU). std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > is a string, so that could be rewritten as:

CryptoPP::BufferedTransformation::ChannelFlush(std::__1::string const&, bool, int, bool)

If this library was built against libstdc++ (GNU), then the symbol from the library would be:

CryptoPP::BufferedTransformation::ChannelFlush(std:::string const&, bool, int, bool)

We can repeat for the second problem child, and it follows the same pattern (libc++, and not libstdc++):

$ nm -g libcryptopp-arm64.a | c++filt | grep CryptoPP::Filter::CopyRangeTo2 | grep " T "
00000000000001c4 T CryptoPP::Filter::CopyRangeTo2(CryptoPP::BufferedTransformation&, unsigned long long&, unsigned long long, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool) const

This can be rewritten as:

CryptoPP::Filter::CopyRangeTo2(CryptoPP::BufferedTransformation&, unsigned long long&, unsigned long long, std::__1::string const&, bool) const

-----

IF you need GNU's libstdc++, then you can build it yourself. Here are the steps:

  1. Download and unpack Crypto++ from the website
  2. Download and unpack cryptopp-mobile.zip. Unpack it right over top the Crypto++ source files
  3. Open the new GNUmakefile, find the iOS rule by searching for the block that begins with IS_IOS
  4. Change this line in the IS_IOS block: CXXFLAGS += -stdlib=libc++. Change it to CXXFLAGS += -stdlib=libstdc++
  5. Do the cross compile...

-----

I downloaded Cocos2D-x and tried to look at its configuration (I'm not a Cmake guy, so I could be wrong with what follows). It has the following in CmakeList.txt:

if(MSVC)
  ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS
                  -wd4251 -wd4244 -wd4334 -wd4005 -wd4820 -wd4710
                  -wd4514 -wd4056 -wd4996 -wd4099)
else()
  set(CMAKE_C_FLAGS_DEBUG "-g -Wall -DCOCOS2D_DEBUG=1")
  set(CMAKE_CXX_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG})
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-exceptions -std=c99")
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -std=c++11 -Wno-deprecated-declarations -Wno-reorder")
  if(CLANG)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
  endif()
endif(MSVC)

If Cmake is doing what I suspect, then its using LLVM's libc++. But its also using -std=c++11, and the GitHub project is not using it. But I'm not sure -std=c++11 makes a difference here.

Just bike shedding, but this is a bad sign: _SCL_SECURE_NO_WARNINGS. If they are blatantly doing that, then they probably have various degrees of of badness and brokenness. (Just my experience with auditing software).


If interested, the __1 is an inline namespace used for versioning. See What are inline namespaces for? and Where does the __1 symbol come from when using LLVM's libc++?.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!