OS X 上的体系结构 x86_64 的未定义符号与 fat 库

Undefined symbols for architecture x86_64 on OS X with fat library

我自己从源代码构建了 libcrypto.alibssl.a,将 darwin64-x86_64-cc(对于 64 位)和 darwin-i386-cc(对于 32 位)指定为 OpenSSL的配置脚本。
使用 lipo 创建胖库并将它们作为依赖项添加到我的 Xcode 项目中。

但是,我遇到了一个未定义的符号错误:

undefined symbols for architecture x86_64:
  "_OPENSSL_ia32cap_P", referenced from:
      _AES_cbc_encrypt in libcrypto.a(aes-x86_64.o)
ld: symbol(s) not found for architecture x86_64

注意: 使用相同的技术对 iOS 效果很好。

lipo -detailed_info libcrypto.a 揭示:

Fat header in: libcrypto.a
fat_magic 0xcafebabe
nfat_arch 2
architecture i386
    cputype CPU_TYPE_I386
    cpusubtype CPU_SUBTYPE_I386_ALL
    offset 48
    size 2700624
    align 2^2 (4)
architecture x86_64
    cputype CPU_TYPE_X86_64
    cpusubtype CPU_SUBTYPE_X86_64_ALL
    offset 2700672
    size 3938432
    align 2^2 (4)

在静态库的情况下,它看起来是 x64 代码生成器中的错误。

最简单的非补丁 openssl 更改解决方法是在代码中的某处添加对 OPENSSL_cleanse 的引用,即使未使用它也是如此。这将修复 link 时间参考。

实际发生的是该符号在某些汇编代码中被引用。

汇编代码只是说 _OPENSSL_ia32cap_P 是一个外部符号,而没有使用交叉 link 来声明它需要被 link 编辑。这适用于 libcrypto.dylib因为引用在生成.dylib文件时被解析;然而,在 .a 的情况下,引用永远不会被解析,因为实际包含该符号的唯一代码是 x86_64cpuid.o,如果您使用它提供的任何例程,它只会被 linked .o.

此文件中的符号包括 OPENSSL_cleanse,因此如果您引用此例程,link 有效。

我偶然发现了同样的 linker 错误,我也尝试添加行 extern int OPENSSL_cleanse(void *ptr, size_t len); 但没有成功。

最终对我有用的是在代码文件的任何位置添加以下行:

uint32_t OPENSSL_ia32cap_P[4] = { 0 };

此外,我使用了以下link作为参考:https://boringssl.googlesource.com/boringssl/+/517073cd4b/crypto/cpu-intel.c#76