【问题标题】:Xcode: how to build for older Intel processors (i5, Core 2 Duo) on i7Xcode:如何在 i7 上为较旧的 Intel 处理器(i5、Core 2 Duo)构建
【发布时间】:2015-11-27 08:44:41
【问题描述】:

我的应用程序在新的 Apple 笔记本电脑上构建然后在更旧的 Apple 笔记本电脑上启动时崩溃。

当使用 llvm 6.1 和 C++11 时,应用程序是在 OSX 10.9 和 10.10 上使用 Xcode 6.4 构建的。 SDK 是 10.10,目标 OSX 是 10.7。优化已关闭。

当 C 运行时加载我的应用程序二进制文件并初始化模块时,崩溃发生的非常早。

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   com.MyCompany.MyApplication     0x000000010cd10e7a _GLOBAL__I_a + 10
1   dyld                            0x00007fff61fd3ceb ImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&) + 265
2   dyld                            0x00007fff61fd3e78 ImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&) + 40
3   dyld                            0x00007fff61fd0871 ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, 

这是在我的任何应用程序代码之前。构建机器(i7 CPU)上不会发生崩溃。 i5 和 Core 2 Duo 机器上会发生崩溃。我怀疑一个扩展的(特定于 CPU 的)指令在加载时造成了崩溃。

当我使用相同的 Xcode、相同的 llvm 等在 Core 2 Duo 机器上构建应用程序时,没有崩溃。

我也在使用自制软件:libmtp、libusb、libusb-compat、cryptopp、curl(使用 c-ares、openssl、nghttp2)、boost。我在必要时指定了 C++11,并指定了 --build-bottle。我静态链接到这些库。

我已尝试在所有库、最终二进制文件等上使用 otool -tV 来查找 SSE 指令。

我尝试将 Xcode LLVM 构建设置“启用附加矢量扩展”设置为“平台”和“SSE3”无济于事。这可能是因为自制软件没有将 --universal 标志从 curl 传递到 openssl 的构建,它是 cryptlib。

我从旧机器中获取了静态库 libcurl.a (CURL)、libssl.a (OpenSSL)、libcrypto.a (OpenSSL)、libz.a (zlib),并将它们添加到我的存储库中。使用 Xcode 将它们链接到我的应用程序可以解决问题。

我还可以使用其他工具来缩小违规指令的范围吗? 崩溃还有其他解释吗?

附录: 除了在旧机器上构建库之外,我还创建了一个概念验证、最小的即时崩溃程序,它报告的崩溃位置略有不同,但演示了问题:

在 i7(配备新 Intel CPU 的新 Apple 计算机)上,使用 homebrew 安装: brew install curl --with-c-ares --with-openssl

然后将此源复制到文件 sse.cpp 中:

#define CURL_STATICLIB
#include <curl/curl.h>
int main(int argc, const char * argv[]) {
    curl_global_init(CURL_GLOBAL_ALL);
    return 0;
}

编译:

clang++ sse.cpp -c -arch x86_64 -I/usr/local/opt/curl/include
clang++ -o a.out sse.o /usr/local/opt/openssl/lib/libssl.a /usr/local/opt/openssl/lib/libcrypto.a /usr/local/opt/zlib/lib/libz.a /usr/local/opt/curl/lib/libcurl.a /usr/local/opt/c-ares/lib/libcares.a -stdlib=libc++ -framework LDAP

现在转移到具有较旧 Intel CPU 的较旧 Apple 计算机,然后将其崩溃:

./a.out

崩溃报告(压缩):

Process:               a.out [569]
...
Code Type:             X86-64 (Native)
Parent Process:        bash [448]
Responsible:           Terminal [339]
...
OS Version:            Mac OS X 10.10.5 (14F27)
...
Crashed Thread:        0  Dispatch queue: com.apple.main-thread
Exception Type:        EXC_BAD_INSTRUCTION (SIGILL)
Exception Codes:       0x0000000000000001, 0x0000000000000000
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   a.out                           0x000000010dbdce3f ENGINE_new + 36
1   a.out                           0x000000010dbe05e3 ENGINE_load_dynamic + 11
2   a.out                           0x000000010dbdf04a ENGINE_load_builtin_engines + 24
3   a.out                           0x000000010dc76b36 Curl_ossl_init + 14
4   a.out                           0x000000010dc5c2a5 curl_global_init + 114
5   a.out                           0x000000010db51d95 main + 37
6   libdyld.dylib                   0x00007fff88b735c9 start + 1

【问题讨论】:

    标签: c++ xcode macos c++11 llvm-clang


    【解决方案1】:

    当您禁用编译器优化时,您的代码是否正常工作?如果没有,试试旧版本的 Xcode 怎么样?它可能只是一个编译器错误,但我希望不是!如果你能找到一个工作编译器或一组编译器选项来检查,你可以使用 LLVM 的 bugpoint 工具来隔离哪个文件被错误编译。

    【讨论】:

    • 关闭优化没有帮助,甚至调试构建崩溃。问题始于旧版本的编译器,但现在 Core 2 Duo 机器和 i7 都使用相同的 Xcode,相同的 llvm。
    • 你可以从 developer.apple.com/downloads 下载旧的 Xcode 版本——看来你得再往前走了。
    • 查看上面的最新发现。
    • 是的,看起来你可以在 cryptopp 中定位错误编译。应该提到如果它是dyld 问题,您可以使用DYLD_ 环境变量(参见dyld 手册页)来确定运行时加载期间发生的情况。 DYLD_PRINT_INITIALIZERS 特别适用。
    • 一切都是静态链接的。系统框架除外。
    【解决方案2】:

    解决方案似乎涉及使用:

    export HOMEBREW_BUILD_BOTTLE=1
    export HOMEBREW_BOTTLE_ARCH=core2
    

    在构建自制程序库时。使用Intel XED,我能够检查发出的机器代码是否有不受支持的指令:

    xed_cmd="/usr/local/bin/xed"
    ar -x libcurl.a
    parts=(*.o)
    for j in "${parts[@]}"; do
        chipcheck=$(${xed_cmd} -i ${j} -chip-check ${chipToCheck})
        chiperrors=$(echo "${chipcheck}" | grep "# Total Chip Check Errors")
    
        if [[ "$chiperrors" != "# Total Chip Check Errors: 0" ]] ; then
            echo ERROR ${libname} ${j} $chiperrors
        fi
    done
    

    【讨论】:

      猜你喜欢
      • 2017-08-21
      • 1970-01-01
      • 2010-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-14
      • 1970-01-01
      • 2011-05-07
      相关资源
      最近更新 更多