MAC OSX Intel LLVM 汇编程序错误(导致 Vorbis OGG 加载程序崩溃)
我在 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 指令集和寄存器),所以我想我会分享它。
奥代
I had mysterious bug in loading Vorbis Ogg files on Mac OSX. The first file is loaded correctly, the second crashes in some code that indicates the file is corrupted, the same happens even if I load the same exact file twice.
After long hours of deep debugging inside Vorbis I found out that the bug is caused by the system function "pow" (double power of) returning a (nan) for a completely valid input, and that happens only on the second call to (ov_read), on the first call the same exact values passed to "pow" returns valid result.
8 hours later and lots of Intel x87 documentation reading I found the problem. Long story short there is a function deep inside vorbis "vorbis_ftoi " that uses this assembly code:
__asm__("fistl %0": "=m"(i) : "t"(f));
Which should push and pop on the Intel FPU Stack. However on LLVM it generates this code:
fld QWORD PTR [ebp-0x20]
fist DWORD PTR [ebp-0x14]
Which pushes on the stack but never pops causing an FPU stack overflow. And that's obviously a bug in LLVM
The proper code generated by GCC looks like this:
fld QWORD PTR [ebp-0x20]
fist DWORD PTR [ebp-0xc]
fstp st(0) // pops off the stack
I wasted a day and a half and some bytes of my brian learning some garbage (x87 Instruction Set and Registers) on this, so I though I would share it.
Auday
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
更简单的补丁,仅在使用 llvm 编译时有效:
不幸的是,我没有足够的声誉来投票支持 OP,但要知道我很感激你的发现。谢谢。
Simpler patch, has affect only when compiling with llvm:
Unfortunately, I don't have enough reputation to vote up the OP, but know that I'm grateful for your find. Thank you.
出色的!谢谢。另一种解决方案是简单地完全删除 asm。这是一个补丁:
Excellent! Thank you. Another solution is to simply remove the asm altogether. Here is a patch: