QEMU can be very useful tool in developing wide range of software from simple application to even linux kernel itself for arm based embedded system. Here is to show how developing and debugging simple application for virtual arm based platform with QEMU is actually easy to people who are lazy so hate to move his/her finger to turn on real board and for poor people who do not have any real hardware.
Note: This post assume Host system is fairly new Ubuntu machine(For my case, its ubuntu 12.04 64bit)
Below is list for bullet items which this post focus.
1. How to build simple c application with a assembly library which can be callable in c function.
2. How to run the executable in Qemu
3. Debugging it with gdb
Phase 0. TOOL Setup
Before delving into programming, we need to check all necessary tools ready. Please refer to below command to install all of them.
First install linaro image tools.
host$ sudo apt-get install linaro-image-tools
To get qemu to work with, there are two ways to building from source code and using apt-get but here I used apt-get as like below.
host$ sudo add-apt-repository ppa:linaro-maintainers/tools host$ sudo apt-get update host$ sudo apt-get install qemu-user-static qemu-system
To be able to compile c and assembly, we need to install crosstool chain for arm.
host$ sudo apt-get install gcc-arm-linux-gnueabi
Phase 1. Creating a simple application made up of c and assembly combination
I wrote some articles in this site how to create CMake project so here I would like to show only source code without detailed explanation about it and why it is needed.
There are 4 files required in the project.
1. main.c # main c source code including main()
2. square.s # assembly file containing functions callable in main()
3. CMakeLists.txt # main cmake project file
4. toolchain-for-qemuarm.cmake # cmake module used for cross compilation for arm target system
So just create below all 4 files in a $(EXAMPLE) directory.
main.c
square.s
CMakeLists.txt
toolchain-for-qemuarm.cmake
Note: Here I used gcc toolchain from Freescale site but you may use other popular toolchain also.
One you have those file, it is easy to build binary which will be run on qemu.
host$ mkdir build; cd build
host$ cmake -DCMAKE_TOOLCHAIN_FILE=../toolchain-for-qemuarm.cmake ..
host$ arm-linux-gnueabi-readelf ./program -a | more
ELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Class: ELF32 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: ARM Version: 0x1 Entry point address: 0x8538 Start of program headers: 52 (bytes into file) Start of section headers: 3592 (bytes into file) Flags: 0x5000002, has entry point, Version5 EABI
host$ qemu-arm-static -L /usr/arm-linux-gnueabi ./program
sum(1, 100) = 101 Hello, ARM World!
host$ qemu-arm-static -g 1234 -L /usr/arm-linux-gnueabi ./program
host$ sudo apt-get install gdb-multiarch
host$ gdb-multiarch
...
(gdb) file program
Reading symbols from /home/<user>/work/qemu/linaro/examples/cassemtest/build/program...done.
(gdb) target remote localhost:1234
Remote debugging using localhost:1234 [New Remote target] warning: Unable to find dynamic linker breakpoint function. GDB will be unable to debug shared library initializers and track explicitly loaded dynamic code. [Switching to Remote target] 0xf67dfc40 in ?? ()(gdb) b main
Breakpoint 1 at 0x85f0: file /home/<user>/work/qemu/linaro/examples/cassemtest/main.c, line 8.
(gdb) c
Continuing. warning: Could not load shared library symbols for 2 libraries, e.g. /lib/libc.so.6. Use the "info sharedlibrary" command to see the complete listing. Do you need "set solib-search-path" or "set sysroot"? Breakpoint 1, main () at /home/<user>/work/qemu/linaro/examples/cassemtest/main.c:8 8 int a=1, b =100;
Conclusion
So far showed how simple application debugging with qemu can be done and hope this post will help app development for embedded system under qemu sandbox which will throw away any worry to break system due to SW bug.