2011-10-11 39 views
9

我有神祕的錯誤在加載在Mac OSX Vorbis的Ogg文件。第一個文件加載正確,第二個崩潰,代碼中指示文件已損壞,即使我加載相同的確切文件兩次也是如此。MAC OSX英特爾LLVM彙編程序錯誤(導致Vorbis格式OGG裝載機崩潰)

在Vorbis內部進行了長時間的深度調試之後,我發現該錯誤是由系統函數「pow」(double power of)返回一個完全有效的輸入(nan)引起的,並且僅在第二個調用(ov_read),在第一次調用時傳遞給「pow」的相同精確值返回有效結果。

8小時後,我發現問題很多,英特爾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指令集和寄存器)在這個,所以我雖然我會分享它。

Auday

+2

如果您認爲自己發現了Apple提供的代碼中的錯誤,則應將其報告給Apple:https://bugreport.apple.com/cgi-bin/WebObjects/RadarWeb.woa/wa/signIn –

+0

done ,謝謝Ned – Auday

+0

+1,因爲我昨天在代碼中發現了一個錯誤,並且也報告了它。至少我的是一個編譯器崩潰,所以調試時間並沒有那麼糟...... –

回答

2

非常好!謝謝。另一個解決方案是簡單地刪除整個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 */ 
3

簡單補丁,已經影響到只有與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,但要知道,我感謝你的發現。謝謝。

+0

我也有這個確切的問題,這個修復工作對我來說。謝謝! – Tod