2011-10-11 6 views
9

Tuve un misterioso error al cargar archivos Vorbis Ogg en Mac OSX. El primer archivo se carga correctamente, el segundo falla en algún código que indica que el archivo está dañado, lo mismo ocurre incluso si cargué el mismo archivo exacto dos veces.MAC OSX Error de Intel LLVM Assembler (causa que el cargador OGG de Vorbis se bloquee)

Después de largas horas de depuración profunda dentro de Vorbis descubrí que el error es causado por la función del sistema "pow" (doble potencia de) que devuelve un (nan) para una entrada completamente válida, y eso ocurre solo en el segundo llamar a (ov_read), en la primera llamada los mismos valores exactos pasados ​​a "pow" devuelve un resultado válido.

8 horas después y mucha documentación de Intel x87 leyendo Encontré el problema. Larga historia corta, hay una función muy dentro Vorbis "vorbis_ftoi" que utiliza este código ensamblador:

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

Cuál debe empujar y hacer estallar en la FPU Pila de Intel. Sin embargo, en LLVM que genera este código:

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

que empuja en la pila, pero nunca aparece provocando un desbordamiento de pila FPU. Y eso es, obviamente, un error en LLVM

El código apropiado generada por GCC se ve así:

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

perdí un día y medio y algunos bytes de mi Brian aprendizaje un poco de basura (Instrucción x87 set y Registros) sobre esto, así que pensé que lo compartiría.

Auday

+2

Si cree que ha encontrado un error en el código suministrado por Apple, debe informarlo a Apple: https://bugreport.apple.com/cgi-bin/WebObjects/RadarWeb.woa/wa/signIn –

+0

hecho , gracias Ned – Auday

+0

+1 porque ayer también encontré un error en su código y también lo informé. Al menos el mío fue un fallo del compilador por lo que el tiempo de depuración no fue tan malo ... –

Respuesta

2

¡Excelente! Gracias. Otra solución es simplemente eliminar el asm por completo. Aquí es un parche:

--- 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

más simple parche, afectará solamente cuando ha compilar con 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 

Por desgracia, no tengo la reputación suficiente para votar hasta el PO, pero sé que estoy Estoy agradecido por tu hallazgo. Gracias.

+0

Tuve este problema exacto también y esta solución funcionó para mí. ¡Gracias! – Tod

Cuestiones relacionadas