Thursday, August 9, 2012

Android native C programs | hello, world ! ARM LINUX | Dynamic Linking

Well, there are a lot of websites online that tell you how to write a android program. But they all are written in java and are compiled to a dalvik executable. Lets get to the basics and write one that runs over your processor rather than the dalvik virtual machine. First of all you need a toolchain. CodeSourcery has a lite edition that is available for free download (linux link, There is a windows version available too). After you download the toolchain (Make sure you have downloaded ARM/GNU Linux version). Untar it, Install it or do whatever you have to get it running (I suggest you to just download the tarball instead of installer). This must give you a folder arm-20xx.xx. We need to copy the libraries required. Decide on your workspace. Create a folder to hold all your work call it /exp. Copy the tool chain to the same folder. Now connect your phone to the computer open shell, command prompt, whichever you are using to access adb and pull /system/lib from it to some new folder in /exp say /exp/lib.

$ adb pull /system/lib /exp/lib

This must pull all the libraries to that folder. Now write your first code hello.c in the root of /exp

#include<stdio.h>
int main()
{
         printf("hello, world! \n ");
         return 0;
}



Now is the time to compile it. Compile it with arm-none-linux-gnueabi-gcc

$./arm-2011.03/bin/arm-none-linux-gnueabi-gcc -c hello.c

This should output a file hello.o, this is our compiled file. But is still not a executable. So now as to get a executable we need to link the file (dynamically) to the libraries. We have already copied libraries to the file /lib. So let us run the loader with required flags to get our executable. What flags do we require???. We need one to tell our program where to start running on execution --entry flag takes care of that. We also need to tell the program where the dynamic linker is when being executed on your phone so we use --dynamic-linker flag. -nostdlib is required so that the compiler doesn't include the standard libraries of linux (The ones in android are quite different). Its is also required to give the path the program should search for its libraries while running on the phone, so the first -rpath. The second one does the work of pointing the linker to the library files as to where the files are stored now (the ones you copied from phone), this is to help the loaded libraries to search for its dependencies. -L, this specifies the path where our library is stored in the computer, the library that is specified by the -l option. -o gives the file name of the output executable. And hello.o is the input file.


$./arm-2011.03/bin/arm-none-linux-gnueabi-ld --entry=main --dynamic-linker /system/bin/linker -nostdlib -rpath /system/lib -rpath ~/exp/lib -L ~/exp/lib -l c -o hello hello.o 

Now we only need to push the file into the phone and execute it.


We can observer that there is a problem in this program. It doesn't exit like the normal programs we used to work with. Instead it has to be terminated manually. How to overcome this defect??. This occurs because we have not asked the program to exit at all. Let us do that now by creating another function that exits the program. We modify the program


#include<stdio.h>
#include<stdlib.h>
int main()
{
         printf("hello, world! \n ");
         return 0;
}

void _close()
{
        exit(main());
}


Now we need to start the program from the _close point so that it calls the main program and then exits it. so compile it same way. But while linking it use --entry flag for _close. 

./arm-2011.03/bin/arm-none-linux-gnueabi-ld --entry=_close --dynamic-linker /system/bin/linker -nostdlib -rpath /system/lib -rpath ~/exp/lib -L ~/exp/lib -l c -o hello hello.o 

Now push this the same way into the phone and execute it


Now the program should exit normally. Cheers!!!