【问题标题】:Problem with Link Time Optimization causing undefined symbols with ASM constants链接时间优化问题导致带有 ASM 常量的未定义符号
【发布时间】:2011-07-17 07:42:35
【问题描述】:

我正在用 llvm-gcc-4.2.1 编译 mplayer。

使用“-O1”(禁用链接时间优化),程序成功编译和链接。使用 '-O2' 或 '-O1 -flto',ld 抱怨未定义的符号:

架构 x86_64 的未定义符号: “_MM_FIX_0_707106781”,引用自: _filter 在 vf_fspp.o “_MM_FIX_0_541196100”,引用自: _filter 在 vf_fspp.o ld:未找到架构 x86_64 的符号 collect2: ld 返回 1 个退出状态

fyi,我的 ld 版本:

@(#)PROGRAM:ld  PROJECT:ld64-123.2
llvm version 2.9svn, from Apple Clang 2.0 (build 137)

我将只关注 MM_FIX_0_707106781,因为其他常量都遵循相同的过程。

MM_FIX_0_707106781 用宏初始化:

DECLARE_ASM_CONST(8, uint64_t, MM_FIX_0_707106781)=FIX64(0.707106781, 14);

计算结果为:

static const uint64_t __attribute__((used, aligned (8))) MM_FIX_0_707106781=0x2d412d412d412d41;

这些常量在 asm 代码中使用:

#define MANGLE(a) "_" #a "(%%rip)" __asm__ 易失性( ... "pmulhw "MANGLE(MM_FIX_0_707106781)", %%mm7 \n\t" ... );

我有一个与 asm 函数类似(相同?)的问题,我可以通过添加以下内容来解决:
".globl "LABLE_MANGLE(functionnamehere)"\n\t"
在每个标签之前,但这些知识并没有帮助我处理这些 ASM 常量。

恐怕这是我能提供的尽可能多的信息。再次,使用 -O1 代码编译、链接和运行。使用 -O2 时,链接器无法找到这些 asm 常量。

谁能提供这个问题的解决方案?谢谢。

【问题讨论】:

    标签: assembly constants undefined llvm symbols


    【解决方案1】:

    以下允许 ffmpeg-0.8 在我的系统上编译:

    ./configure --cc=i686-apple-darwin10-gcc-4.2.1 --enable-gpl --enable-nonfree
    

    【讨论】:

      【解决方案2】:

      感谢所有花时间考虑我的问题的人,但是我刚刚意识到我搞砸了我的编译工具,现在可以正常编译了。

      问题在于 mplayer make 脚本调用“cc”进行编译,期望 cc == gcc。我的系统不是这种情况。 cc 被符号链接到一些不同版本的 gcc。一旦我将 cc 符号链接到 gcc,我就可以使用 -O4 编译项目(在默认的 mplayer 配置脚本中设置)。

      结论:不正确配置的编译器工具会导致链接时发生冲突。通过在构建的所有阶段使用相同的编译器来解决。

      编辑:实际上 llvm-gcc 仍然会因 -O4 而失败,但其他编译器(gcc-4.5.2 和 gcc42,这是 Apple 的 gcc 版本)成功。其他两个编译器都不接受 -flto 标志,因此链接时间优化仍然失败。至少我很高兴我可以使用 -O2、-O3 等进行编译,这是我提出这个问题的主要原因。

      如果我愿意,我当然希望能够使用 llvm-gcc 编译器(在 -O1 以上的级别),但是您应该考虑这个问题已半解决,因为其他两个编译器可以正常使用此代码.

      【讨论】:

        【解决方案3】:

        llvm-link 中有一个错误 - 它不考虑来自嵌入式 asm 的符号。除了从 C 中的同一模块的某处引用相同的符号之外,我不知道有任何体面的解决方法。如果您正在执行单独的编译,这不是问题,因为使用了本机链接器。对于 LTO,将使用 LLVM 链接器,这是有缺陷的。

        编辑:我没有注意到static,这意味着内联asm和符号都在同一个模块中,这是一个不同的错误。

        【讨论】:

        • 这不是真的。此处常量被明确标记为“已使用”,因此无论在何处使用,都应由优化器保留。
        • @Anton Korobeynikov,似乎没有帮助,因为整个模块没有链接 - 没有遵循来自嵌入式 asm 的引用。如果__asm__ 在一个模块中而常量在另一个模块中,并且后者在第一个模块之后链接,则应该发生这种情况。
        • 这是预期的行为,编译器将汇编程序视为文本,因此您应该仔细告知它您正在做一些奇怪的事情。使用静态变量(因为它没有外部可见性)是您绝对应该告知编译器的事情(在这种情况下 - 通过操作数)。
        • @Anton Korobeynikov,我知道。这个故事的重点是 llvm 本身很容易出现这种情况:如果您尝试将自己的 LTO 应用于 llvm,则不会链接到 JIT 回调。
        【解决方案4】:

        嗯,这绝对是一个错误。如果您认为这是编译器错误,您有多种选择:

        1. 向 Apple 的 bugtracker 报告,因为您似乎正在使用 XCode 附带的 llvm-gcc
        2. 尝试获取树顶 llvm 和 llvm-gcc(顺便说一句,现在已弃用)并尝试重现该问题(或者,也可以获取 clang)。如果重现 - 然后填写 LLVM PR。

        这就是通常处理编译器错误的方式:)

        但是,在我看来,错误在源代码中。在这里,您假设最终对象中与此静态常量对应的符号名称将具有某种形式。这通常是实现定义的东西,编译器可以以任意方式更改名称(因为它是静态的,因此 - 在外部不可见)。

        尝试删除“静态”并检查问题是否仍然存在。或者(这是正确的方法),您应该修复您的内联汇编程序并通过内联汇编程序操作数提供您的常量。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-06-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-10-01
          • 1970-01-01
          相关资源
          最近更新 更多