In this blog, I log my initial effort to try out emulating embedded hardware with QEMU.
Background:
QEMU can emulate the execution of different architecture and platform. It is a machine emulator. It use dynamic translation of virtual machine code to host code. It has its own intermediate language using its tiny code generator (TCG). In our case, we need to modify the following modules. The major C files we would need to modify are /vl.c (defines start of execution main(), and sets up a virtual machine environment given specs such as ram size, devices, number of CPUs etc), /cpu.c /exec-all.c /exec.c /cpu-exec.c (following main execution). All the virtual hardwares are under /hw/. Qemu emulates a number of hardware. (we need to add or find peripherals in this part) Frontend of TCG is for different CPU architecture, we would not modify front end. Backend of TCG is for host system, we would not modify backend either.
SensorTag is an IoT sensor provided by TI. It is composed of two cpu, ARM cortex-M0 and cortex-M3. M3 is for application and M0 for wireless communication physical layer. It also has five sensors. SensorTag is provided with rich software development support. It has an IDE called Code Composer Studio which compile the firmware for M3. Although firmware for M0 is not configurable by development tools provided by Ti, we may dump its flash and memory through communicating to it with device driver on M3. But in this work, we will focus on application processor first. Or if we find an easy way to extract baseband firmware, we will do that instead. Besides the Code Composer Studio, there also exist a flash writer provided by TI. All of these tools communicate to the board through cJTAG. It would be nice if we can port this hardware architecture to QEMU, but in this blog, we will focus on working on an already ported architecture.
By default, QEMU translates all guest architectures (14 in total) to it's own internal IR called TCG (Tiny Code Generator). This IR is not robust enough for our analyses, so we leverage the translation module from S2E to translate a step further to LLVM. In order to handle taint propagation through QEMU's helper functions, we use Clang to translate the relevant helper functions to the LLVM IR. This allows us to have complete and correct information flow models for code that executes within QEMU, without having to worry about architecture-specific details. But in this blog, we will not go to that deep.
Log:
The first thing is to find a SoC ported into QEMU before. And I find three potential example.
https://gnu-mcu-eclipse.github.io/qemu/
https://github.com/gnu-mcu-eclipse/qemu
https://gnu-mcu-eclipse.github.io/qemu/
Maple – LeafLab Arduino-style STM32 microcontroller board
NUCLEO-F103RB – ST Nucleo Development Board for STM32 F1 series
NetduinoGo – Netduino GoBus Development Board with STM32F4
NetduinoPlus2 – Netduino Development Board with STM32F4
STM32-E407 – Olimex Development Board for STM32F407ZGT6
STM32-H103 – Olimex Header Board for STM32F103RBT6
STM32-P103 – Olimex Prototype Board for STM32F103RBT6
STM32-P107 – Olimex Prototype Board for STM32F107VCT6
STM32F4-Discovery – ST Discovery kit for STM32F407/417 lines
STM32F429I-Discovery – ST Discovery kit for STM32F429/439 lines
STM32F103RB
STM32F107VC
STM32F405RG
STM32F407VG
STM32F407ZG
STM32F429ZI
STM32L152RE
Then we will set up the environment for developing. And we will compare the advantages and disadvantages in each setup. We will first set up the second solution which is eclipse MCU and see how it works.
After following the tutorial on their website, we set up a eclipse environment for debugging STM32 program on Qemu. It port the mentioned architecure before into Qemu and use the gdbserver provided by Qemu to debug the internal loaded program. Eclipse is attaching a arm-gdb to the port opened by Qemu.
The advantage of this way is that we can debug our program running on a hardware SoC by leaving the emulation job to Qemu.
The disadvantage of this way is that we can not directly debug Qemu while the emulation is running.
However, we can achieve our goal of debug the Qemu directly while executing the emulation. First, after a little hack of the makefile from the original author, we managed to build the modified Qemu with debugging symbol embedded. So we set up a new Eclipse project and import the make system of the Qemu source. Then we debug the Qemu binary with the source. Then we also open a gdbserver on the Qemu and we create another project and import the source for the embedded application. And we attach the remote gdb debugger to the running Qemu.
But in our case, we want to know the internals of how Qemu start up code, and we want to know how real firmware binary eactly work with Qemu. So the blink.elf is not a firmware binary dump. It is the source of firmware binary dump. With this framework, it is designed for us to evaluate our userland application but not full system emuolation.
So we go to the second way. We set up the environment for STM32 project. Since the main stream is similar to this setup, we will only discuss about this setup. First, we compile the source for the STM32 version of Qemu. Then we setup eclipse for debugging it. We import according to make file and set up the gdb debugger. The following figure shows the setup. (In this setup we use the Qemu to emulate the execution of a firmware binary which blink led).
After we are able to debug the qemu source code. We make it open a gdbserver port. And in this case we can see the execution of binary image inside it. The starting address of the binary is 0x5680.
The partial disassembled code is listed as following: