链接时间优化问题导致 ASM 常量未定义符号
我正在使用 llvm-gcc-4.2.1 编译 mplayer。
使用“-O1”(禁用链接时间优化),程序可以成功编译和链接。使用“-O2”或“-O1 -flto”,ld 抱怨未定义的符号:
Undefined symbols for architecture x86_64: "_MM_FIX_0_707106781", referenced from: _filter in vf_fspp.o "_MM_FIX_0_541196100", referenced from: _filter in vf_fspp.o ld: symbol(s) not found for architecture x86_64 collect2: ld returned 1 exit status
仅供参考,我的 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__ volatile( ... "pmulhw "MANGLE(MM_FIX_0_707106781)", %%mm7 \n\t" ... );
我在 asm 函数中遇到了类似(相同?)的问题,我可以通过添加来解决:".globl "LABLE_MANGLE(此处函数名称)"\n\t"
在每个标签之前,但是这些知识并没有帮助我了解这些 ASM 常量。
恐怕我能提供的信息就这么多了。再次使用 -O1 来编译、链接和运行代码。使用 -O2 时,链接器无法找到这些 asm 常量。
谁能提供这个问题的解决方案?谢谢。
I am compiling mplayer with llvm-gcc-4.2.1.
With '-O1' (which disables link time optimization), the program successfully compiles and links. With '-O2' or '-O1 -flto', ld complains of undefined symbols:
Undefined symbols for architecture x86_64: "_MM_FIX_0_707106781", referenced from: _filter in vf_fspp.o "_MM_FIX_0_541196100", referenced from: _filter in vf_fspp.o ld: symbol(s) not found for architecture x86_64 collect2: ld returned 1 exit status
fyi, my version of ld:
@(#)PROGRAM:ld PROJECT:ld64-123.2
llvm version 2.9svn, from Apple Clang 2.0 (build 137)
I'll focus just on MM_FIX_0_707106781, as the other constants all follow the same procedure.
MM_FIX_0_707106781 is initialized with the macro:
DECLARE_ASM_CONST(8, uint64_t, MM_FIX_0_707106781)=FIX64(0.707106781, 14);
which evaluates to:
static const uint64_t __attribute__((used, aligned (8))) MM_FIX_0_707106781=0x2d412d412d412d41;
These constants are used in asm code:
#define MANGLE(a) "_" #a "(%%rip)" __asm__ volatile( ... "pmulhw "MANGLE(MM_FIX_0_707106781)", %%mm7 \n\t" ... );
I had a similar (the same?) problem with asm functions that I was able to resolve by adding:".globl "LABLE_MANGLE(functionnamehere)"\n\t"
before each label, but that knowledge has not helped me with these ASM constants.
That is as much information as I can provide, I'm afraid. Once again, with -O1 the code compiles, links, and runs. With -O2 the linker fails to find these asm constants.
Can anyone offer a solution to this problem? Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
感谢所有花时间考虑我的问题的人,但是我刚刚意识到我搞砸了我的编译工具,现在可以正常编译了。
问题是 mplayer 让脚本调用“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 以上的级别),但是您应该考虑这个问题半解决,因为其他两个编译器可以正常使用此代码。
Thanks to all who took the time to consider my question, however I just realized that I screwed up my compile tools, and am now able to compile normally.
The issue was that the mplayer make scripts invoke 'cc' to compile, with the expectation that cc == gcc. This was not the case on my system; cc was symlinked to some different version of gcc. As soon as I symlinked cc to gcc, I got the project to compile with -O4 (as set in the default mplayer configure script).
In conclusion: improperly configured compiler tools were causing conflicts at link time. Resolved by using the same compiler at all stages of build.
Edit: Actually llvm-gcc still fails with -O4, but the other compilers (gcc-4.5.2 and gcc42, which is Apple's gcc version) succeed. Both other compilers do not accept the -flto flag, so link-time-optimization is still failing. I am at least happy that I can compile with -O2, -O3, etc, which is the main reason I was motivated to pose this question.
Naturally I would like to be able to use the llvm-gcc compiler if I wish (at a level above -O1), however you should consider this question semi-resolved, as the other two compilers are working properly with this code.
嗯,这绝对是一个错误。如果您认为这是编译器错误,您有多种选择:
这就是人们通常处理编译器错误的方式:)
但是,在我看来,错误存在于源代码中。在这里,您假设最终对象中与此静态常量对应的符号名称将采用某种形式。这通常是实现定义的东西,编译器可以以任意方式更改名称(因为它是静态的,因此 - 外部不可见)。
尝试删除“static”并检查问题是否仍然存在。或者(这是正确的方法),您应该修复内联汇编器并通过内联汇编器操作数提供常量。
Well, this is definitely a bug. If you think, that this is compiler bug you have several options:
This is how one normally would deal with compiler bugs :)
However, as it seems to me, the bug is in the source code. Here you're assuming that the name of the symbol corresponding to this static constant in the final object will be of some form. This is generally implementation defined stuff and compiler can change the name in arbitrary way (since it's static and thus - not externally visible).
Try to remove "static" and check whether there the problem still exists. Alternatively (and this is the proper way), you should fix your inline assembler and provide your constant via inline assembler operand.
llvm-link 中存在一个错误 - 它不考虑嵌入式汇编中的符号。除了在 C 中的同一模块中引用相同的符号之外,我不知道有什么合适的解决方法。如果您正在进行单独的编译,那么这不是问题,因为使用了本机链接器。对于 LTO,将使用 LLVM 链接器,但它是有缺陷的。
编辑:我没有注意到
static
,这意味着内联asm和符号都在同一个模块中,这是一个不同的错误。There is a bug in llvm-link - it does not consider symbols from an embedded asm. I don't know of any decent workaround other than referencing the same symbol somewhere from the same module in C. If you're doing a separate compilation, it is not a problem, as a native linker is used. For the LTO an LLVM linker will be used, and it is flawed.
EDIT: I have not noticed
static
, which means that both inline asm and a symbol are in a same module, and it is a different bug.以下内容允许 ffmpeg-0.8 在我的系统上编译:
The following allowed ffmpeg-0.8 to compile on my system: