Monday, May 05, 2014

Setting up IDA SDK 6.5 on Mac OS X 10.9 (Mavericks)

(This blog post is a wrap-up of the thread I started on Hex-Rays support forum)

Prerequisites



  • Mac OS X 10.9 (Mavericks)
  • IDA Pro 6.5
  • IDA SDK (downloadable from here -  the password should have been provided to you while purchasing IDA Pro)


$ md5 idasdk65.zip
MD5 (idasdk65.zip) = 4afa4c11ae8480f0753d5b2f87b61213


Note: if you would like to perform all the steps below within a virtual machine, it is perfectly legal to do so. Just use VMWare Fusion 6 to create a new virtual machine from the local recovery partition. The same trick should work with Parallel, but I did not test it.


Installing GCC from MacPorts



IDA SDK would only compile with 32-bit GCC.


Unfortunately, OS X 10.9 and XCode 5 do not provide GCC anymore, as Apple completely switched to LLVM (gcc command is only an alias). For the rest of this post, I will rely upon GCC 4.7 provided by MacPorts 2.2.1. Feel free to explore other options, such as HomeBrew. However, to download and build GCC from source, MacPorts requires a compiler! Therefore the proper installation order is:


1. Install Apple C(++) compiler


At this point, “full” XCode 5 install is required. XCode call be downloaded from the AppStore, or from Apple Developers site (the former requires a valid AppStore account, whereas the latter only requires free registration).


After install, do not forget to get command-line tools also:
$ xcode-select --install


… and to accept XCode EULA from command-line, in case you never started the GUI:
$ sudo xcodebuild -license


Confirm that LLVM has been properly installed:
$ gcc --version
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.1.0
Thread model: posix


Confirm that SDK has been properly installed (and keep that path, you will need it later on):
$ xcrun --sdk macosx --show-sdk-path
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk


Note: it is possible to install command-line tools only by simply typing gcc in a terminal, or to get them from Apple Developers. However, this will not install the OS 10.9 SDK required by IDA SDK later on.


2. Get MacPorts from www.macports.org (installer version 2.2.1 was the most recent available at the time of writing).


You might need to log out and in again to get /opt/local/bin in your PATH.


3. Install GCC from MacPorts.


You will need to get the 32-bit flavor of GCC. This can be achieved through several means:


$ port install gcc47 +i386
… will only install the 32-bit version of GCC


$ port install gcc47 +universal
… will install all archs specified in /opt/local/etc/macports/macports.conf


In any case, you can grab a coffee. Building GCC from source could take hours.


You might get the following warning if you did not install the “full” XCode suite. It seems that you can safely ignore for now, but remember that you will need OS 10.9 SDK later on anyway.
$ sudo port install gcc47 +universal
Warning: xcodebuild exists but failed to execute
Warning: Xcode does not appear to be installed; most ports will likely fail to build.
--->  Computing dependencies for gcc47
--->  Updating database of binaries: 100.0%
--->  Scanning binaries for linking errors: 100.0%
--->  No broken files found.


4. Do not forget to alias GCC to the MacPorts version.


$ port select --list gcc
Available versions for gcc:
mp-gcc47
none (active)


$ port select --set gcc mp-gcc47
Selecting 'mp-gcc47' for 'gcc' succeeded. 'mp-gcc47' is now active.


$ gcc --version
gcc (MacPorts gcc47 4.7.3_3+universal) 4.7.3
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


Setting up Qt



IDA SDK depends on Qt, version 4.8.4. Qt header files are required for compiling “graphical” plugins.


The “stock” Qt 4 source distribution will not build on Mac OS X 10.9:
util/qdeclarativefontloader.cpp:87:52: error: addition of default argument on redeclaration makes this constructor a default
     constructor
QDeclarativeFontObject::QDeclarativeFontObject(int _id = -1)


(Please note that compiling “stock” Qt requires LLVM - and not GNU GCC - to be the default gcc alias).


There is no hope of getting an official fix, as this OS version is unsupported:
../../include/QtCore/../../src/corelib/global/qglobal.h:331:6: warning: "This version of Mac OS X is unsupported" [-W#warnings]
#    warning "This version of Mac OS X is unsupported"


Therefore the best way to go is to install qt4-mac from MacPorts (do not use qt4-mac-devel, which is older and seemingly unmaintained). Note: at this point, you can grab a second coffee, as compiling Qt could also take hours.


At the time of writing qt4-mac is a port of Qt version 4.8.5 - close enough to do the job.


Installing qt4-mac is enough to get all the required headers, but will not produce Qt libraries that could replace those bundled with IDA, as those libraries were generated specifying a different namespace at compile time.


It should be possible to edit the Portfile and add the extra required option (-qtnamespace QT), but that would probably break all other Qt-dependent binaries in MacPorts - so I did not bother to explore that option.


At this point we end up in the error-prone-but-yet-working situation of having MacPorts Qt 4.8.5 (patched) headers in /opt/local and IDA prebuilt Qt 4.8.4 libraries in /Applications/IDA Pro/idaq.app/Contents/Frameworks


$ ls
QtCore.framework QtGui.framework QtHelp.framework QtNetwork.framework QtSql.framework QtXml.framework libQtCLucene.4.dylib


IDA SDK “makefiles” have hardcoded references to the following include paths:
-I../../include/
-I"/Users/Shared/Qt/4.8.4/include/QtCore"
-I"/Users/Shared/Qt/4.8.4/include/QtGui"
-I"/Users/Shared/Qt/4.8.4/include/QtXml"
-I"/Users/Shared/Qt/4.8.4/include"
-I.


You can choose to edit the makefiles. I chose the other way around: creating a lot of symlinks.


$ mkdir /Users/Shared/Qt/


$ mkdir /Users/Shared/Qt/4.8.4/


$ ln -s /opt/local/include/ /Users/Shared/Qt/4.8.4/include


Failure to symlink the include directory will result in the following error message at compile-time:
qwindow.cpp:10:19: fatal error: QWidget: No such file or directory
compilation terminated.


$ ln -s /opt/local/bin/ /Users/Shared/Qt/4.8.4/bin


Failure to symlink the bin directory will result in the following error message at compile-time:
/bin/sh: /Users/Shared/Qt/4.8.4/bin/moc: No such file or directory
make[2]: *** [obj/x86_mac_gcc_32/moc_myactions.o32] Error 127
make[1]: *** [qwindow] Error 1
make: *** [plugins] Error 1


$ ln -s /Applications/IDA\ Pro/idaq.app/Contents/Frameworks/ /Users/Shared/Qt/4.8.4/lib


Failure to symlink the lib directory will result in the following error message at compile-time:
g++: error: /Users/Shared/Qt/4.8.4/lib/QtXml.framework/QtXml: No such file or directory
g++: error: /Users/Shared/Qt/4.8.4/lib/QtGui.framework/QtGui: No such file or directory
g++: error: /Users/Shared/Qt/4.8.4/lib/QtCore.framework/QtCore: No such file or directory
make[2]: *** [../../bin/plugins/qwindow.pmc] Error 1
make[1]: *** [qwindow] Error 1
make: *** [plugins] Error 1


Grabbing IDA libraries



1. Unzip IDA SDK archive. For the rest of this post, I will assume it has been unzipped into its default location: ~/idasdk65


(Documentation sometimes refers to idasrc instead, but unfortunately we do not have a copy of this one :)


2. IDA author usually recommends putting a full copy of IDA under ~/idasdk65/bin


However, it is enough to copy or symlink the following library from IDA installation directory:
/Applications/IDA Pro/idaq.app/Contents/MacOS/libida.dylib


Failure to do so will result in the following error message at compile-time:
ld: library not found for -lida
collect2: error: ld returned 1 exit status


If you would like to compile 64-bit plugins, also grab the following library:
/Applications/IDA Pro/idaq.app/Contents/MacOS/libida64.dylib

Compiling



1. As stated in the documentation, export the following environment variables:


$ export __MAC__=1


$ export MACSDK=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk


Remember that path? You got it from:
$ xcrun --sdk macosx --show-sdk-path
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk


2. Run the compilation script:


$ chmod 755 bin/idamake.pl


$ bin/idamake.pl


If the latter command did not return any error, you are all set!


Compiling a plugin



Let’s take findcrypt2 plugin as an example.


Compiling 32-bit Mac OS X version:


$ cd ~/idasdk65/plugins/findcrypt2


$ make


$ file ~/idasdk65/bin/plugins/findcrypt.pmc
~/Users/newsoft/idasdk65/bin/plugins/findcrypt.pmc: Mach-O dynamically linked shared library i386


Compiling 64-bit Mac OS X version:


$ export __EA64__=1


$ cd ~/idasdk65/plugins/findcrypt2


$ make


$ file ~/idasdk65/bin/plugins/findcrypt.pmc64
~/Users/newsoft/idasdk65/bin/plugins/findcrypt.pmc64: Mach-O dynamically linked shared library i386


I made both binaries are available for download [32-bit] [64-bit].


Note: IDA64 is actually a 32-bit application that handles 64-bit files - therefore plugins for IDA64 are also expected to be 32-bit libraries. Defining __X64__ at compile-time will actually build a full 64-bit library, but that should be useful for building debugger modules only.


Wrapping up



This documentation is provided in “worked for me” license.


I might provide limited support for this, but be sure to provide me with very detailed error messages. And please do not ask for “leaked” IDA or IDA SDK versions.

In the end, the whole process sounds really awkward. If anybody knows of a better solution to do it, feel free to share!