Wasp Lisp is a small cross platform lisp by Scott Dunlop that I've written about before and MOSREF is the secure remote injection framework that is one of the applications written with it.

I've been wanting to get Wasp running on Android and Gonk (the low level Android layer of Firefox OS) for debugging and small applications. One of the nice features of Wasp is being able to have a minimal interpreter running on a platform and send byte code from another system to that interpreter which is loaded and run. You can even send the bytecode compiler itself to be loaded and run in the interpreter to get a full system on the target. This is the basis of how MOSREF works where the drone gets sent code to run from the console system.

Standalone Toolkit

Building Wasp for Android requires generating a standalone toolchain from the Android NDK. This results in a vesion of gcc and libraries that can be run from conventional makefiles and configure scripts.

To generate a standalone toolchain to build Wasp I used:

$NDK_ROOT/build/tools/make-standalone-toolchain.sh \ --platform=android-8 \ --install-dir=$STK_ROOT

Replace NDK_ROOT with the path to the Android SDK and STK_ROOT with the destination where you want the standalone toolkit installed. The android-8 in the platform makes the standalone toolkit generate applications for FroYo and above (See STABLE-APIS.html.

Adding $STK_ROOT/bin to the PATH will make the compiler available:

export PATH=$PATH:$STK_ROOT/bin

Building libevent for Android

The Wasp virtual machine uses libevent to enable asynchronous operations. Building this for Android using the standalone toolkit is straightforward:

wget https://github.com/downloads/libevent/libevent/libevent-2.0.21-stable.tar.gz tar xvf libevent-2.0.21-stable.tar.gz cd libevent-2.0.21-stable ./configure --host=arm-linux-androideabi --prefix=$STK_ROOT make make install

This configures libevent to be built using the ARM compilers in the standalone toolkit and to install the resulting libraries in the same install location as the toolkit. This makes it easy for other applications to find and link with the library.

Building the Wasp stub for Android

A Wasp VM stub file is used for generating Wasp applications. The bytecode for an application is appended to the stub file and the result made to be executable. By having stubs for various operating systems and architectures you can create executables specific to them easily. To build the Android stub:

git clone git://github.com/swdunlop/WaspVM.git cd WaspVM STRIP=arm-linux-androideabi-strip \ CC=arm-linux-androideabi-gcc \ CFLAGS="-I $STK_ROOT/include -L $STK_ROOT/lib" \ ARCH=arm-linux \ OS=android \ make

To build we define the correct version of the build programs to compile for ARM and set the architecture and OS to stop the build system from picking up the host system version of these. The result is a waspvm-android-arm-linux stub in the stubs directory.

Creating the host Wasp programs

To easily create Wasp programs for different platforms we'll need versions of them for the host we are running on. By doing a 'clean' followed by a 'make' on the host we'll clean out the Android build files and rebuild what's needed for the host. The 'clean' process doesn't remove the stub file we created in the previous step which still allows us to do android Wasp programs.

make clean make

This produces a waspvm-linux-x86_64 stub in my stubs directory. To generate the Wasp interpreter and other programs:

make repl

Exit out of the repl with (exit) and there will be a wasp , waspc and waspld program for the host system. Now we can make a version of wasp for Android:

cd mod ../waspc -exe ../awasp -platform android-arm-linux bin/wasp.ms

The waspc command takes a stub file (defined by the platform or stub argument) and appends the bytecode resulting from the compilation of the Wasp lisp code given as an argument. wasp.ms is the source for the intepreter. The output is set as awasp which is our executable for running on Android. We can use a similar command for producing Android versions of the other Wasp programs. MOSREF for example:

../waspc -exe ../amosref -platform android-arm-linux bin/mosref.ms

Running on Android

Running these executables on Android involves pushing them to somewhere writeable on the phone. If you have a rooted Android device (or a Firefox OS device) you can push them pretty much anywhere. On my non-rooted Jellybean Galaxy Note 2 I'm limited to just /data/local/tmp :

adb push awasp /data/local/tmp adb shell cd /data/local/tmp chmod 0755 awasp ./awasp >> (+ 1 2 3) :: 6

This gives you a running Wasp interpreter. To develop and do interesting things on the phone you really need the Wasp mod files and the stub files copied over:

adb push mod /data/local/tmp adb push stubs /data/local/tmp adb shell cd /data/local/tmp ./awasp >> (import "lib/http-client") :: #t >> (http-response-body (http-get "http://icanhazip.com/")) :: "xxx.xxx.xxx.xxx

" >> (exit)

MOSREF Android drone

It's simple now to create a MOSREF drone that runs on Android. Make sure the MOSREF console has a stubs directory containing the Android stub then create the drone as:

console> drone drone1 myphone android-arm-linux Drone executable created. Listening for drone on 10000...

Copy the created drone1 onto the phone and run it:

adb push mod/drone1 /data/local/tmp adb shell cd /data/local/tmp chmod 0755 drone1 ./drone1

Now on the console you can see the drone on the phone:

console> nodes NODES: console online address: 192.168.1.101 port: 10000 myphone online console> on myphone sh ls ...directory listing... console on myphone do (print "hello

") ...prints hello on the phone 'adb shell' session... console> on myphone load lib/http-file-server.ms :: spawn-http-file-server console> on myphone do (offer-http-file 8080 "/test" "text/plain" "Hello world!") :: [queue 1F5DD00]