You are on page 1of 3

How To Cross Compile A Binary For iDevices by cawan (cawan[at]ieee.org or chuiyewleong[at]hotmail.

com) on 20/10/2013 The gcc that comes with OSX without Xcode being installed does not include cross compilation toolchain in generating software for idevices. Let's verify. awans-MacBook-Pro:~ cawan$ gcc i686-apple-darwin11-llvm-gcc-4.2: cawans-MacBook-Pro:~ cawan$ which /usr/bin/gcc cawans-MacBook-Pro:~ cawan$ ls -l lrwxr-xr-x 1 root wheel 12 Sep cawans-MacBook-Pro:~ cawan$ ls -l lrwxr-xr-x 1 root wheel 32 Sep ../llvm-gcc-4.2/bin/llvm-gcc-4.2 cawans-MacBook-Pro:~ cawan$ ls -l -rwxr-xr-x 1 root wheel 117168 no input files gcc /usr/bin/gcc 26 2012 /usr/bin/gcc -> llvm-gcc-4.2 /usr/bin/llvm-gcc-4.2 26 2012 /usr/bin/llvm-gcc-4.2 -> /usr/llvm-gcc-4.2/bin/llvm-gcc-4.2 Sep 26 2012 /usr/llvm-gcc-4.2/bin/llvm-gcc-4.2

So, the gcc is just a symbolic link to llvm-gcc-4.2. Let's check the llvm-gcc-4.2. awans-MacBook-Pro:~ cawan$ /usr/llvm-gcc-4.2/bin/llvm-gcc-4.2 i686-apple-darwin11-llvm-gcc-4.2: no input files cawans-MacBook-Pro:~ cawan$ /usr/llvm-gcc-4.2/bin/llvm-gcc-4.2 -arch armv7 llvm-gcc-4.2: error trying to exec '/usr/llvm-gcc-4.2/bin/arm-apple-darwin11-llvm-gcc-4.2': execvp: No such file or directory cawans-MacBook-Pro:~ cawan$ /usr/llvm-gcc-4.2/bin/llvm-gcc-4.2 -arch i686 i686-apple-darwin11-llvm-gcc-4.2: no input files Well, the llvm-gcc-4.2 is just a forwarder to an appropriate compiler, either i686-apple-darwin11-llvm-gcc-4.2 or arm-apple-darwin11-llvm-gcc-4.2, which is decided by "-arch" parameter. When "-arch" is not specified, the default is i686-apple-darwin11-llvm-gcc-4.2. Now, let us install a copy of Xcode (I am using Xcode 4.5 here). After the installation is completed, the llvm-gcc-4.2 can be found in 2 locations. cawans-MacBook-Pro:bin cawan$ pwd /Applications/Xcode.app/Contents/Developer/usr/llvm-gcc-4.2/bin cawans-MacBook-Pro:bin cawan$ ls -l total 1464 -rwxr-xr-x@ 1 cawan admin 127776 Sep 8 2012 gcov-4.2 -rwxr-xr-x@ 1 cawan admin 544416 Sep 8 2012 i686-apple-darwin11-llvm-g++-4.2 -rwxr-xr-x@ 1 cawan admin 544416 Sep 8 2012 i686-apple-darwin11-llvm-gcc-4.2 -rwxr-xr-x@ 1 cawan admin 117168 Aug 5 2012 llvm-c++-4.2 -rwxr-xr-x@ 1 cawan admin 257552 Sep 8 2012 llvm-cpp-4.2 -rwxr-xr-x@ 1 cawan admin 117168 Sep 8 2012 llvm-g++-4.2 -rwxr-xr-x@ 1 cawan admin 117168 Sep 8 2012 llvm-gcc-4.2 cawans-MacBook-Pro:bin cawan$ cawans-MacBook-Pro:bin cawan$ pwd /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/llvmgcc-4.2/bin cawans-MacBook-Pro:bin cawan$ ls -l total 2344 -rwxr-xr-x@ 1 cawan admin 555104 Sep 8 2012 arm-apple-darwin10-llvm-g++-4.2 -rwxr-xr-x@ 1 cawan admin 546896 Sep 8 2012 arm-apple-darwin10-llvm-gcc-4.2 -rwxr-xr-x@ 1 cawan admin 130816 Sep 8 2012 gcov-4.2 -rwxr-xr-x@ 1 cawan admin 551008 Sep 8 2012 i686-apple-darwin10-llvm-g++-4.2 -rwxr-xr-x@ 1 cawan admin 546896 Sep 8 2012 i686-apple-darwin10-llvm-gcc-4.2 -rwxr-xr-x@ 1 cawan admin 106112 Sep 8 2012 llvm-c++-4.2 -rwxr-xr-x@ 1 cawan admin 255728 Sep 8 2012 llvm-cpp-4.2 -rwxr-xr-x@ 1 cawan admin 106112 Sep 8 2012 llvm-g++-4.2 -rwxr-xr-x@ 1 cawan admin 106112 Sep 8 2012 llvm-gcc-4.2 cawans-MacBook-Pro:bin cawan$ So, the cross compiler is only available in Platforms/iPhoneOS.platform/Developer/. Now, let us try to build a simple binary to run in idevice.

cawans-MacBook-Pro:bin cawan$ ./llvm-gcc-4.2 i686-apple-darwin10-llvm-gcc-4.2: no input files cawans-MacBook-Pro:bin cawan$ ./llvm-gcc-4.2 -arch armv7 arm-apple-darwin10-llvm-gcc-4.2: no input files cawans-MacBook-Pro:bin cawan$ cat cawan_hello.c #include <stdio.h> main() { printf("\nhello cawan\n"); } cawans-MacBook-Pro:bin cawan$ ./llvm-gcc-4.2 -arch armv7 cawan_hello.c -o cawan_hello In file included from /usr/include/sys/_types.h:33, from /usr/include/_types.h:27, from /usr/include/stdio.h:67, from cawan_hello.c:1: /usr/include/machine/_types.h:34:24: error: arm/_types.h: No such file or directory In file included from /usr/include/_types.h:27, from /usr/include/stdio.h:67, from cawan_hello.c:1: ... ... ... cawans-MacBook-Pro:bin cawan$ Well, the headers and libraries of idevice should be specified for the cross compilation process. It is located in the directory of iphone SDK being installed together with Xcode. cawans-MacBook-Pro:bin cawan$ ls -l /Applications/Xcode.app/Contents/Developer/Platforms/ iPhoneOS.platform/Developer/SDKs/ total 0 drwxr-xr-x@ 8 cawan admin 272 Oct 17 09:28 iPhoneOS5.1.sdk drwxr-xr-x@ 10 cawan admin 340 Oct 15 23:47 iPhoneOS6.0.sdk cawans-MacBook-Pro:bin cawan$ I have 2 versions of SDKs installed, 5.1 and 6.0. Now, I am going to use version 6.0. cawans-MacBook-Pro:bin cawan$ ./llvm-gcc-4.2 -arch armv7 -o cawan_hello -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/ iPhoneOS6.0.sdk cawan_hello.c cawans-MacBook-Pro:bin cawan$ ls -l cawan_hello -rwxr-xr-x 1 cawan admin 12604 Oct 20 15:13 cawan_hello cawans-MacBook-Pro:bin cawan$ file cawan_hello cawan_hello: Mach-O executable arm cawans-MacBook-Pro:bin cawan$ lipo -info cawan_hello Non-fat file: cawan_hello is architecture: armv7 cawans-MacBook-Pro:bin cawan$ Fine, it seems the binary is ready. Let's run it in iphone environment. Turn on the ssh server in iphone and use tcprelay to connect into the iphone. cawans-MacBook-Pro:python-client cawan$ python tcprelay.py 22:2222 Forwarding local port 2222 to remote port 22 Now, it is ready to copy the cawan_hello into the iphone via port 2222. cawans-MacBook-Pro:bin cawan$ scp -P 2222 cawan_hello root@127.0.0.1:/Applications/ root@127.0.0.1's password: cawan_hello 100% 12KB 12.3KB/s 00:00 cawans-MacBook-Pro:bin cawan$ The cawan_hello is copied into /Applications/ of the iphone. So, it is ready to connect into the iphone and run the cawan_hello. cawans-MacBook-Pro:bin cawan$ ssh -p 2222 root@127.0.0.1 root@127.0.0.1's password: snows-iPhone:~ root# cd /Applications snows-iPhone:/Applications root# ls cawan_hello cawan_hello* snows-iPhone:/Applications root# ./cawan_hello -sh: ./cawan_hello: Bad CPU type in executable

snows-iPhone:/Applications root# Unfortunately, it seems the processor architecture of my iphone is not armv7. From the back cover of my iphone, I can see its model number is A1241. Well, it is iphone 3G and its processor architecture is armv6, not armv7. Let's recompile the binary again. cawans-MacBook-Pro:bin cawan$ ./llvm-gcc-4.2 -arch armv6 -o cawan_hello -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/ iPhoneOS6.0.sdk cawan_hello.c ld: file is universal (4 slices) but does not contain a(n) armv6 slice: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/ iPhoneOS6.0.sdk/usr/lib/crt1.o for architecture armv6 collect2: ld returned 1 exit status cawans-MacBook-Pro:bin cawan$ Well, it seems iphone sdk 6.0 is not compatible with armv6 architecture. Let's use iphone sdk 5.1 instead. cawans-MacBook-Pro:bin cawan$ ./llvm-gcc-4.2 -arch armv6 -o cawan_hello -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/ SDKs/iPhoneOS5.1.sdk cawan_hello.c cawans-MacBook-Pro:bin cawan$ Copy the new cawan_hello into the iphone and run it again. cawans-MacBook-Pro:bin cawan$ scp -P 2222 cawan_hello root@127.0.0.1:/Applications/ root@127.0.0.1's password: cawan_hello 100% 12KB 12.3KB/s 00:00 cawans-MacBook-Pro:bin cawan$ ssh -p 2222 root@127.0.0.1 root@127.0.0.1's password: snows-iPhone:~ root# cd /Applications snows-iPhone:/Applications root# ls cawan_hello cawan_hello* snows-iPhone:/Applications root# ./cawan_hello Killed snows-iPhone:/Applications root# Good, the cawan_hello is capable to run in my iphone but it is killed by the iOS. This is because the iOS will verify the signature of a binary first before allowing it to run. If the signiture verification check is failed, then the iOS will kill the binary which attempting to run. Anyway, since I know my iphone is jailbroken, so I can simply use ldid to perform pseudo-signing to my cawan_hello. Let's try again. cawans-MacBook-Pro:bin cawan$ ldid -S cawan_hello cawans-MacBook-Pro:bin cawan$ scp -P 2222 cawan_hello root@127.0.0.1:/Applications/ root@127.0.0.1's password: cawan_hello 100% 13KB 12.5KB/s 00:00 cawans-MacBook-Pro:bin cawan$ ssh -p 2222 root@127.0.0.1 root@127.0.0.1's password: snows-iPhone:~ root# cd /Applications snows-iPhone:/Applications root# ls cawan_hello cawan_hello* snows-iPhone:/Applications root# ./cawan_hello hello cawan snows-iPhone:/Applications root# Excellent, the cawan_hello can run properly in my iphone now. There are some arguments about is it possible for Xcode 4.5 in generating binary for armv6 based idevices such as iphone 3G or iPod touch 2G. From this exercise, it is proven the Xcode 4.5 is able to generate armv6 binary by specifiying the base sdk as 5.1 and target architecture as armv6.