Debugging ARM binary on Ubuntu Host using qemu ARM and GDB

In our previous two posts, “How to use gdb for debugging application programs” and “Using GDB to debug functions defined in another file in C” we have shown some basic steps for how you can use GDB to debug your programs running on X86 based desktops.

In this post, we will show you how you can debug the ARM binary compiled for some embedded ARM based target on the ARM QEMU, but this same things will be working for debugging on real target except how you run the binary on qemu.

Download latest ARM toolchain from https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads , we downloaded gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2 which is the latest toolchain when writing this post.

export the toolchain path

$ mkdir -p /home/myuser/workspace
$ cd workspace

Copy the downloaded toolchain to this workspace directory, extract and export the bin path so we have the binaries in terminal path,

$ tar xvf gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2
$ export PATH=$PATH:/home/myuser/workspace/gcc-arm-none-eabi-10-2020-q4-major/bin

once you exported path, you can see arm-none-eabi-gcc is available in terminal.

Now lets try to create simple helloworld program,

$ vim helloworld.c
#include <stdio.h>

int main(int argc, char **argv) {
        int num = 0;
        printf("helloworld\n");
        printf("addition: %d\n", 3+2);
        return 0;
}

Above simple program prints helloworld and also prints addition of two numbers. We will compile this program using below command,

$ arm-linux-gnueabihf-gcc -o helloworld helloworld.c -static -g

here as you can see,

  • Notice, here we used “arm-linux-gnueabihf-gcc” installed on Ubuntu machine instead of toolchain GCC, since to avoid library mismatches, we need to use the toolchain installed on Ubuntu and that too with -static option to be able to successfully debug with qemu-arm.
  • we also have added “-static” since we will be running this program inside qemu, it seems there is no correct library versions matched between the toolchain we have used to compile helloworld and how qemu-arm works and also when we tried to run helloworld compiled without -static, our program got crashed always.
  • The ending “-g” is used to add the debugging symbols which will be required for debugging with GDB.

Now we can run the program with qemu-arm as,

$ qemu-arm -L gcc-arm-none-eabi-10-2020-q4-major/lib -g 8090 ./helloworld

this command will wait for the debugger to connect on port 8090, here you can use any port.

Connect GDB

$ arm-none-eabi-gdb
(gdb) file helloworld
Reading symbols from helloworld...
(gdb) target remote:8090
Remote debugging using :8090
0x0000816c in _start ()

Now, we are all set to debug this program.

Set a breakpoint at main,

(gdb) break main

Now, type continue on gdb console,

(gdb) c
Continuing.

Breakpoint 1, main (argc=1, argv=0xfffef184) at helloworld_src/helloworld.c:6
6		int num = 0;

As you can see above, our program stopped at main, after we set breakpoint and asked to continue.

Now, we will continue again, as this post is only meant to show how to setup debugging environment, in our next post we will list how you can set the breakpoints in GDB. “Setting different breakpoints in GDB while debugging”

(gdb) c
Continuing.
[Inferior 1 (process 1) exited normally]

Here, once you typed continue without setting any further breakpoints, you can see the program exited normally and we got the output printed on terminal where qemu-arm was waiting on 8090 port,

$ qemu-arm -L gcc-arm-none-eabi-10-2020-q4-major/lib -g 8090 ./helloworld
helloworld
addition: 5

Leave a Comment