Nat! bio photo


Senior Mull

Twitter Github Twitch

Build mulle-clang on a virtual ARM machine on QEMU/Ubuntu

To get an ARM executable for mulle-clang there are three options:

  1. build the compiler on a native ARM machine
  2. build a cross-compiler for ARM
  3. build a compiler in a VM that emulates ARM

Option #1 is obvious the easiest, but I have no ARM hardware that would be capable for this task (i.e. I don’t think a RaspberryPI can do it). Option #2 will be investigated in the future. That leaves option #3 which is todays topic.


  • QEMU
  • 4 CPU cores
  • 16 GB RAM
  • 32 GB Free diskspace

Create VM

There is no easy iso installer to create an emulated ARM VM, but again there are options:

Use a prefabricated image with debian stretch (preferred)

Pick a pre-fabricated image by Blah Cats. I tried this and it works well. You only might wonder how much trust you want to put into VM images that are distributed by Black Hat attendants 😉.

Use a cloud image with ubuntu xenial

This works, but the cloud image is very sluggish, so that I abandoned it. I am putting the instructions at the end of this entry, for future reference.


Build mulle-clang in the VM

Now comes the easiest but also the slowest part: build the compiler. I estimate this can take a whole day. Following the build instructions we do.

1. Install basic pre-requisites

Assuming you are logged in as root:

apt-get install sudo curl ninja-build
# usermod -aG sudo nat  # make yourself a sudo user optionally

Getting ninja is somewhat crucial, as the standard Makefile could not pick up an interrupted build, which can be excruciating, if something goes wrong.

2. Get build script

mkdir mulle-clang
cd mulle-clang
curl -L -O ""

3. Run the build script

chmod 755 install-mulle-clang
DEBIAN_FRONTEND=noninteractive ./install-mulle-clang --clang-prefix /opt

Check the cmake output for:

-- Found SWIG: /usr/bin/swig3.0 (found version "3.0.12")

If you have anything less than 3.0.12, the build is likely to fail, which happened on debian/stretch. There the packaged swig was the wrong version 3.0.10. I fixed this with:

curl -O
curl -O
sudo dpkg -i swig_3.0.12-2_arm64.deb swig3.0_3.0.12-2_arm64.deb

4. Install into system

./install-mulle-clang install --symlink-prefix /usr/local

If this works, you should be able to run the compiler on ARM! But since this takes so much time (I didn’t wait for it to finish), I’ll be exploring option #2 next.

There is a gist with a more verbose script that also supports running the VM with a bridge.

Use a cloud image with ubuntu xenial continued

I am using xenial here, because this was the last cloud image I could find that supported the raw QEMU image format. The instructions are an amalgamation of Ubuntu Wiki ARM64/QEMU and an askubuntu entry

Installation of such a cloud image is somewhat tricky, since you can not easily set the password.

1. Install prerequisites:

sudo apt-get install qemu qemu-system-arm qemu-efi cloud-image-utils

2. Download the Ubuntu cloud image:

It is necessary to expand the image to at least 20GB before going on:

curl -L -O ""
qemu-img resize "xenial-server-cloudimg-arm64-uefi1.img" +20G

3. Create the ARM boot environment

dd if=/dev/zero of=flash0.img bs=1M count=64
dd if=/usr/share/qemu-efi/QEMU_EFI.fd of=flash0.img conv=notrunc
dd if=/dev/zero of=flash1.img bs=1M count=64

4. Create patch instructions for cloud image

These creates instructions for the cloud image to change the root password, so you can log in:

cat > user-data <<EOF
password: vflbochum
chpasswd: { expire: False }
ssh_pwauth: True

cloud-localds user-data.img user-data
rm user-data

5. Create the VM

You should customize the following command and adapt the number of cores with -smp (max 8), ram -m and the mac address -device ...,mac= .Don’t skimp on CPUs and RAM.

You can create a random MAC address with MAC Address Generator.

sudo qemu-system-aarch64 \
   -smp "4" \
   -m "16G" \
   -cpu cortex-a57 \
   -M virt \
   -nographic \
   -drive file="flash0.img",format=raw,if=pflash \
   -drive file="flash1.img",format=raw,if=pflash \
   -drive file="xenial-server-cloudimg-arm64-uefi1.img",id=hd0,if=none \
   -drive file="user-data.img",format=raw \
   -device virtio-blk-device,drive=hd0 \
   -device virtio-net-device,netdev=net0,mac="72-FF-25-61-D6-C9" \
   -netdev tap,id=net0

The virtual machine should now start up and after quite a while, you should see the cloud image configuring itself. You can’t login with the root password, until this configuration is done.

Post a comment

All comments are held for moderation; basic HTML formatting accepted.

E-mail: (not published)