MonoGame / MonoGame.Dependencies

The MonoGame binary dependencies submodule.
38 stars 51 forks source link

/FreeImage.NET/MacOS/libfreeimage.dylib contains Intel AVX instructions, causing SIGILL signal #61

Open wjlandryiii opened 8 years ago

wjlandryiii commented 8 years ago

When I try building my content using Pipeline.app, I receive this error:

Build started 9/26/2015 9:16:58 AM

/Users/wjl/Projects/testfna/testfna/Content/icon.bmp
/Users/wjl/Projects/testfna/testfna/Content/icon.bmp: error: Importer 'TextureImporter' had unexpected failure!
System.ExecutionEngineException: SIGILL
  at Microsoft.Xna.Framework.Content.Pipeline.ContentImporter`1[Microsoft.Xna.Framework.Content.Pipeline.Graphics.TextureContent].Microsoft.Xna.Framework.Content.Pipeline.IContentImporter.Import (System.String filename, Microsoft.Xna.Framework.Content.Pipeline.ContentImporterContext context) [0x00000] in <filename unknown>:0 
  at MonoGame.Framework.Content.Pipeline.Builder.PipelineManager.ProcessContent (MonoGame.Framework.Content.Pipeline.Builder.PipelineBuildEvent pipelineEvent) [0x00000] in <filename unknown>:0 
Build 0 succeeded, 1 failed.

Time elapsed 00:00:00.25.

When debugging with lldb, I found that the illegal instruction was located in libfreeimage.dylib:

$ lldb mono
(lldb) target create "mono"
Current executable set to 'mono' (i386).
(lldb) process launch /Users/wjl/Projects/MonoGame/Tools/MGCB/bin/MacOS/AnyCPU/Debug/MGCB.exe /@:/Users/wjl/Projects/testfna/testfna/Content/Content.mgcb
Process 9666 launched: '/usr/local/bin/mono' (i386)
warning: (i386) /Library/Frameworks/Mono.framework/Versions/4.0.4/lib/mono/4.5/mscorlib.dll.dylib empty dSYM file detected, dSYM was created with an executable with no debug info.
Build started 9/26/2015 9:30:15 AM

/Users/wjl/Projects/testfna/testfna/Content/icon.bmp
Process 9666 stopped
* thread #1: tid = 0xc5d7ae, 0x03148297 libfreeimage.dylib`TagLib::TagLib() + 21, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
    frame #0: 0x03148297 libfreeimage.dylib`TagLib::TagLib() + 21
libfreeimage.dylib`TagLib::TagLib() + 21:
-> 0x3148297:  vxorps %xmm0, %xmm0, %xmm0
   0x314829b:  vmovups %xmm0, 0x4(%esi)
   0x31482a0:  movl   $0x0, 0x14(%esi)
   0x31482a7:  movl   %eax, 0xc(%esi)
(lldb)

The vxorps instruction is an Intel AVX instruction that is not supported on older chips. According to wikipedia, the AVX extension was introduced in 2011, so any chip older than that doesn't support the extension.

To work around this problem, I used homebrew to compile libfreeimage.dylib from source and replaced the dylib in the .app with the freshly compiled homebrew version:

$ brew install freeimage --build-from-source --universal
==> Downloading https://downloads.sourceforge.net/project/freeimage/Source%20Distribution/3.17.0/FreeImage3170.zip
==> Downloading from http://iweb.dl.sourceforge.net/project/freeimage/Source%20Distribution/3.17.0/FreeImage3170.zip
######################################################################## 100.0%
==> Patching
patching file Makefile.fip
Hunk #4 succeeded at 69 with fuzz 2.
patching file Makefile.gnu
==> make -f Makefile.gnu
==> make -f Makefile.gnu install PREFIX=/usr/local/Cellar/freeimage/3.17.0
==> make -f Makefile.fip
==> make -f Makefile.fip install PREFIX=/usr/local/Cellar/freeimage/3.17.0
🍺  /usr/local/Cellar/freeimage/3.17.0: 7 files, 65M, built in 4.2 minutes
$
wjlandryiii commented 8 years ago

Also, I don't know if any other binaries in this project contain AVX instructions, this is the first time I've ever used this software and I was following a tutorial on how to load an image.

tomspilman commented 8 years ago

@dellis1972 @KonajuGames - Did we just build FreeImage with the wrong build settings for Mac?

wjlandryiii commented 8 years ago

Yeah, it's not a bug in the FreeImage source code. The compiler must have been set to target a CPU that supports those instructions, and my Core 2 Duo doesn't support those instructions.

dellis1972 commented 8 years ago

I think the original libfreeimage.dylib was sourced from home-brew..

first the 64 bit version was downloaded.. then the 32 bit then they were merged to provide a universal binary.

Looks like @KonajuGames https://github.com/KonajuGames modified it recently , not sure how that was compiled/ put together.

On 26 September 2015 at 19:55, wjlandryiii notifications@github.com wrote:

Yeah, it's not a bug in the FreeImage source code. The compiler must have been set to target a CPU that supports those instructions, and my Core 2 Duo doesn't support those instructions.

— Reply to this email directly or view it on GitHub https://github.com/Mono-Game/MonoGame.Dependencies/issues/61#issuecomment-143479460 .

KonajuGames commented 8 years ago

My Mac is from 2010, and there was nothing special with building it. The makefile provided with FreeImage specifies i386 and x86_64 as the CPU targets. I'll have a closer look.

wjlandryiii commented 8 years ago

I think I figured it out.

It looks like when you compile from source, homebrew will check the hardware you are compiling on and set compiler flags to optimize for that specific hardware. To disable the automatic hardware optimizations, you can use the homebrew command line option --build-bottle. When building for a bottle, homebrew will use the oldest processor to base it's compiler optimizations on to allow it to run on all hardware.

I bet your 2010 mac supports AVX, and that's why it was compiled that way. You can check if your system supports AVX by running the command sysctl -n hw.optional.avx1_0. "0" means the hardware does not support AVX, while "1" means the hardward does support AVX.

I tried this on a mac I have access to that supports AVX. Here is the proof that it works:

MiniDVR:~ minidvr$ brew install freeimage --build-from-source --universal
==> Downloading https://downloads.sourceforge.net/project/freeimage/Source%20Distribution/3.17.0/FreeImage3170.zip
Already downloaded: /Library/Caches/Homebrew/freeimage-3.17.0.zip
==> Patching
patching file Makefile.fip
Hunk #4 succeeded at 69 with fuzz 2.
patching file Makefile.gnu
==> make -f Makefile.gnu
==> make -f Makefile.gnu install PREFIX=/usr/local/Cellar/freeimage/3.17.0
==> make -f Makefile.fip
==> make -f Makefile.fip install PREFIX=/usr/local/Cellar/freeimage/3.17.0
🍺  /usr/local/Cellar/freeimage/3.17.0: 7 files, 63M, built in 107 seconds
MiniDVR:~ minidvr$ otool -arch i386 -tv /usr/local/Cellar/freeimage/3.17.0/lib/libfreeimage.dylib | grep vxorps | head
00004922    vxorps  %ymm0, %ymm0, %ymm0
00004f74    vxorps  %xmm0, %xmm0, %xmm0
00006525    vxorps  %ymm0, %ymm0, %ymm0
00008f6b    vxorps  %ymm0, %ymm0, %ymm0
0000a8ae    vxorps  %xmm0, %xmm0, %xmm0
0000d116    vxorps  %xmm0, %xmm0, %xmm0
0000d702    vxorps  %ymm0, %ymm0, %ymm0
0000d8eb    vxorps  %ymm0, %ymm0, %ymm0
0000e115    vxorps  %xmm0, %xmm0, %xmm0
0000e67b    vxorps  %xmm0, %xmm0, %xmm0
MiniDVR:~ minidvr$ brew remove freeimage
Uninstalling /usr/local/Cellar/freeimage/3.17.0... (7 files, 63M)
MiniDVR:~ minidvr$ brew install freeimage --build-from-source --universal --build-bottle
==> Downloading https://downloads.sourceforge.net/project/freeimage/Source%20Distribution/3.17.0/FreeImage3170.zip
Already downloaded: /Library/Caches/Homebrew/freeimage-3.17.0.zip
==> Patching
patching file Makefile.fip
Hunk #4 succeeded at 69 with fuzz 2.
patching file Makefile.gnu
==> make -f Makefile.gnu
==> make -f Makefile.gnu install PREFIX=/usr/local/Cellar/freeimage/3.17.0
==> make -f Makefile.fip
==> make -f Makefile.fip install PREFIX=/usr/local/Cellar/freeimage/3.17.0
🍺  /usr/local/Cellar/freeimage/3.17.0: 7 files, 63M, built in 107 seconds
MiniDVR:~ minidvr$ otool -arch i386 -tv /usr/local/Cellar/freeimage/3.17.0/lib/libfreeimage.dylib | grep vxorps | head
MiniDVR:~ minidvr$
tomspilman commented 6 years ago

@dellis1972 - Is this still a thing we need to fix or can we close this?

dellis1972 commented 6 years ago

We should probably update free image net with this stuff. That said our min MacOS is 10.7 now for the Pipeline tool, not sure that will even run on a machine that old?