Recentely I’ve been involved with simple ARM assembly programming at university. The toolchains provided to me were either clunky (CYGWIN on Windows) or totally broken (the linux binaries), so I had to come up with something.
Installing the ARM toolchain
The first thing you need to compile an ARM program is a compiler, of course.
Fortunately, the ARM architecture is widely supported nowadays, therefore this won’t be a problem.
I’ve choosen the GCC-based toolchain, which you can probably find in your favourite distro’s package repository.
In my case (Archlinux) I had to install the following packages from AUR:
The last one is actually the debugger, but we’ll need it later anyway.
To test your compiler, try to save this snippet in a file, e.g. empty.s
To compile it, we will assemble and link it:
I everything goes well, you should obtain an empty
ELF executable.
Unfortunately, unless you have an ARM machine at hand, it will be difficult to execute it: the easiest way to overcome this is to use qemu
.
Debugging with qemu and GDB
After having installed qemu, you will be able to run your program as follows:
To understand what is really going on in the program, we’ll connect gdb
to qemu, that will serve as a gdb server.
We first need to be sure that the program has been built with debugging symbols turned on:
To run our program, we’ll use:
so that it halts on the first instruction (useful for debugging). The -g parameter specifies which port will be used by the gdb server to listen for clients.
There are many GUIs one can use to make GDB more palatable, but none of them satisfied me, and I sticked to the integrated terminal UI that gdb offers.
Here’s what you need to do to connect to qemu:
We first load the debugging symbols using the file
command, then we connect to our remote target.
##Crash course on GDB
The TUI provided by GDB is good enough to debug simple (and complex) programs: press Ctrl+x
and then A
to active it: above your usual GDB command prompt, you will see the source being debugged.
Enter this command to have a good view of the registers.
You should end up with something like this:
These are some basic commands to know, only one key press away:
- s Step by a single instruction
- b Set a breakpoint. You can use this in many ways, like
b source.s:312
where source.s is the source and 312 the line number where you want the breakpoint. - c Continue until next breakpoint
For more commands, like setting watchs or printing memory data, you can follow the official guide.