Monday, August 1, 2011

Debugging ARM files with arm-elf-gdb (Simulation)

First off, ensure you have downloaded the GNU ARM Toolchain, including the debugger (arm-elf-gdb). The following works beautifully in Ubuntu 10.04 (Lucid), and will work similarly under Cygwin.

We need an ARM assembly file. Here is one right here: flash-v1.s. (Note that the comments are preceded by @ symbols, not semicolons).

Create an executable file by following this post.


Life@Phi:$ make flash-v1.elf

arm-elf-as --gdwarf2 -mcpu=arm7tdmi -o flash-v1.o flash-v1.s
arm-elf-ld -o flash-v1.elf flash-v1.o
rm flash-v1.o


Open the ELF file with the debugger.

Life@Phi:$ arm-elf-gdb flash-v1.elf 
GNU gdb 6.8
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-linux-gnu --target=arm-elf"...
(gdb) 
GDB can be used to step through programs loaded on microcontrollers (via JTAG, etc), but here we will only look at simulating hardware. To do this, we need to initiate the simulator:

(gdb) target sim 
Connected to the simulator.
Now we 'load' our ELF file in to our simulator.
(gdb) load

Loading section .text, size 0x1c vma 0x8000
Start address 0x8000

Notice that the start address corresponds to the _start variable set in flash-v1.s.
There are hundreds of commands available in GDB. This is by no means the only (or best) way to debug programs, but here we go. Right now the code is loaded in our simulator, and we need to start running it. start will run the program until it reaches the beginning of the main function. (Alternatively, run will run to program until it finds a breakpoint).
(gdb) start

Breakpoint 1 at 0x8004: file flash-v1.s, line 62.
Starting program: /your/directory/flash-v1.elf 
main () at flash-v1.s:62
62    mov r4, #LED_port       @ Load the address of the LED port
Current language:  auto; currently asm

All that extra information in there is due to the -gdwarf2 debugging flag used during assembly. Without this information, it can be extremely difficult to debug and follow along.
The instruction 'mov r4, #LED_port' is the next instruction to be executed (i.e. it has not been executed yet).

Now for a little bit of information gathering. Let's inspect the values at the registers:

(gdb) info registers 
r0             0x0 0
r1             0x0 0
r2             0x0 0
r3             0x0 0
r4             0x0 0
r5             0x0 0
r6             0x0 0
r7             0x0 0
r8             0x0 0
r9             0x0 0
r10            0x0 0
r11            0x0 0
r12            0x0 0
sp             0x800 0x800
lr             0x0 0
pc             0x8004 0x8004

fps            0x0 0
cpsr           0x13 19
Let's execute ONE instruction of our program.

(gdb) step
main_loop () at flash-v1.s:70
70    mov r5, #Value1         @ Load the value Value1 into R5

It is important to remember this will execute the previously listed instruction, 'mov r4, #LED_port', not the currently displayed instruction. We verify this by inspecting the registers again.


(gdb) info registers 
r0             0x0 0
r1             0x0 0
r2             0x0 0
r3             0x0 0
r4             0x10000000 268435456
r5             0x0 0
r6             0x0 0
r7             0x0 0
r8             0x0 0
r9             0x0 0
r10            0x0 0
r11            0x0 0
r12            0x0 0
sp             0x800 0x800
lr             0x0 0
pc             0x8008 0x8008
fps            0x0 0
cpsr           0x13 19


We can also examine (x) specific parts of memory.
(gdb) x 0x10000000
0x10000000: 0x00000000
(gdb) step
71    strb    r5, [r4]        @ and store this value (a byte) to
(gdb) step
76    mov r5, #Value2         @ Load the value Value2 into R5
(gdb) x 0x10000000
0x10000000: 0x000000ff

Notice how the value at 0x10000000 changes from 0x00 to 0xFF.

In summary, here are some of the important commands for gdb:
target [object/process, e.g. sim]
load
start
info registers
step
x [addr]
and I didn't mention it, but the invaluable help.

3 comments:

  1. when I type "target sim" it says "sim" undefined:


    frankmp40@frankmp40-Inspiron-1120:~/Desktop$ arm-elf-gdb flash-v1.elf &
    [6] 7356
    frankmp40@frankmp40-Inspiron-1120:~/Desktop$ GNU gdb 6.8
    Copyright (C) 2008 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law. Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "--host=i686-linux-gnu --target=arm-elf"...
    (gdb)
    GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2
    Copyright (C) 2010 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law. Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "i686-linux-gnu".
    For bug reporting instructions, please see:
    .
    (gdb) target sim
    Undefined target command: "sim". Try "help target".

    ReplyDelete
  2. Hey Frank,
    Remove that first ampersand, and you will be fine.
    Btw, try to keep all comments and questions inside the Moodle forum (applies to UNSW ELEC2142 students only).

    ReplyDelete
  3. If i don't have simulator with me for target . I mean just imagine i have only code to do debugging then which command i have to use .

    ReplyDelete