MAC OSX Intel LLVM 汇编程序错误(导致 Vorbis OGG 加载程序崩溃)

Posted

技术标签:

【中文标题】MAC OSX Intel LLVM 汇编程序错误(导致 Vorbis OGG 加载程序崩溃)【英文标题】:MAC OSX Intel LLVM Assembler bug (causes Vorbis OGG loader to crash) 【发布时间】:2011-12-04 23:41:50 【问题描述】:

我在 Mac OSX 上加载 Vorbis Ogg 文件时遇到了神秘的错误。第一个文件正确加载,第二个文件在某些​​代码中崩溃,表明文件已损坏,即使我两次加载相同的文件也会发生同样的情况。

在 Vorbis 内部进行了长时间的深度调试后,我发现该错误是由系统函数“pow”(双重幂)为完全有效的输入返回 (nan) 引起的,并且仅在第二次调用时发生到 (ov_read),在第一次调用时,传递给“pow”的完全相同的值返回有效结果。

8 小时后,阅读大量 Intel x87 文档后,我发现了问题所在。长话短说,在 vorbis "vorbis_ftoi" 内部有一个函数使用这个汇编代码:

__asm__("fistl %0": "=m"(i) : "t"(f));

应该在英特尔 FPU 堆栈上推送和弹出。但是在 LLVM 上,它会生成以下代码:

fld    QWORD PTR [ebp-0x20]
fist   DWORD PTR [ebp-0x14]

压入堆栈但从不弹出导致 FPU 堆栈溢出。这显然是 LLVM 中的一个错误

GCC 生成的正确代码如下所示:

fld    QWORD PTR [ebp-0x20]
fist   DWORD PTR [ebp-0xc]
fstp   st(0)        // pops off the stack

我在这方面浪费了一天半的时间和我的一些字节来学习一些垃圾(x87 指令集和寄存器),所以我想分享一下。

奥黛

【问题讨论】:

如果您认为在 Apple 提供的代码中发现了错误,您应该向 Apple 报告:bugreport.apple.com/cgi-bin/WebObjects/RadarWeb.woa/wa/signIn +1 因为我昨天也在他们的代码中发现了一个错误并报告了它。至少我的是编译器崩溃,所以调试时间还不错...... 【参考方案1】:

太棒了!谢谢你。另一种解决方案是完全删除 asm。这是一个补丁:

--- lib/os.h 2011-11-13 20:36:24.000000000 -0500
+++ lib/os.h        2011-11-15 18:45:00.000000000 -0500
@@ -93,27 +93,16 @@
 typedef ogg_int16_t vorbis_fpu_control;

 static inline void vorbis_fpu_setround(vorbis_fpu_control *fpu)
-  ogg_int16_t ret;
-  ogg_int16_t temp;
-  __asm__ __volatile__("fnstcw %0\n\t"
-          "movw %0,%%dx\n\t"
-          "andw $62463,%%dx\n\t"
-          "movw %%dx,%1\n\t"
-          "fldcw %1\n\t":"=m"(ret):"m"(temp): "dx");
-  *fpu=ret;
 

 static inline void vorbis_fpu_restore(vorbis_fpu_control fpu)
-  __asm__ __volatile__("fldcw %0":: "m"(fpu));
 

 /* assumes the FPU is in round mode! */
 static inline int vorbis_ftoi(double f)  /* yes, double!  Otherwise,
                                              we get extra fst/fld to
                                              truncate precision */
-  int i;
-  __asm__("fistl %0": "=m"(i) : "t"(f));
-  return(i);
+    return (int)floor(f+.5);
 
 #endif /* Special i386 GCC implementation */

【讨论】:

【参考方案2】:

更简单的补丁,仅在使用 llvm 编译时有效:

--- Xiph\vorbis\os.h    Mon Mar 28 08:42:43 2011
+++ Xiph\vorbis\os.h    Thu Feb 02 14:20:27 2012
@@ -81,7 +81,7 @@


 /* Special i386 GCC implementation */
-#if defined(__i386__) && defined(__GNUC__) && !defined(__BEOS__)
+#if defined(__i386__) && defined(__GNUC__) && !defined(__BEOS__) && !defined(__llvm__)
 #  define VORBIS_FPU_CONTROL
 /* both GCC and MSVC are kinda stupid about rounding/casting to int.
    Because of encapsulation constraints (GCC can't see inside the asm

很遗憾,我没有足够的声望来投票支持 OP,但我很感激您的发现。谢谢。

【讨论】:

我也遇到了这个确切的问题,这个修复对我有用。谢谢!

以上是关于MAC OSX Intel LLVM 汇编程序错误(导致 Vorbis OGG 加载程序崩溃)的主要内容,如果未能解决你的问题,请参考以下文章

objdump 如何发出 intel 语法

Mac OSX 系统目录结构(转)

适用于 Mac 的 Intel VTune Profiler 错误:无法与目标通信

mac osx wine 1.7.5 源码编译方法及中文乱码的解决

Mac OSX 上的 Eclipse CDT 问题

苹果的osx 10.5何时发布?