Intel® Simics® Simulator for Intel® FPGAs: User Guide

ID 784383
Date 4/01/2024
Public
Document Table of Contents

9.1.1.2. Debugging with GDB from Host PC with Intel® Simics® Simulator GDB Server

This method consists of using the internal GDB Server in the Intel® Simics® simulator to debug the software running in the target system from the Host PC. You can use this method for any source code for which you have an ELF file that contains the debug information.

This method debugs code on the processor in "bare metal" form, while the earlier method was limited to debugging a user-mode application.

For debugging with GDB from host PC with Intel® Simics® Simulator GDB server, you must have the following items:

  • A Linux Host PC with GDB application installed.
  • Intel® Simics® simulator includes the GDB server that allows you to connect from the host PC.
  • ELF (binary with debug information) of the software application to be debugged is available in host PC along with the source code of the application.

The chart below depicts the relationship and sequence of using GDB for debugging in the method.

The following section details the steps to debug a Test Application Binary testGdb by using this method.

In the Intel® Simics® simulator CLI, the Test Application Binary is transferred to the target system using the Intel® Simics® simulator internal TFTP server. Subsequently, the establish the GDB connection using the new-gdb-remote command, this connection is used by the Linux Host to debug the Test Application in the Target System.

# Intel Simics simulator CLI 

# Step 1. Setup Intel Simics tftp dir: /home/simicsUser/gdbDir directory
simics> service_node_cmp0.set-tftp-directory “/home/simicsUser/gdbDir”

# Step 2. Add symbol file of testGdb and add a breakpoint at main.
simics> enable-debugger 
Debugger enabled.

simics> add-symbol-file "/home/simicsUser/gdbDir/testGdb" 

simics> bp.source_location.break main
Breakpoint 1: 0x1 (planted)
Setting new inspection object: system...agilex_hps.core[0]
[tcf] Breakpoint 1 on execution in context system...agilex_hps.core[0]

# Step 3. Start GDB session
simics> new-gdb-remote
[gdb0 info] Attached to CPU: system...agilex_hps.core[0]
[gdb0 info] Awaiting GDB connections on port 9123.
[gdb0 info] Connect from GDB using: "target remote localhost:9123"
[gdb0 info] Attached to system...agilex_hps.core[0]
simics> run

# Step 4a. After step 4 the simulation stops and this is seen
[tcf] Breakpoint 1 on execution in context system...agilex_hps.core[0]
Now debugging the arm-cortex-a55 system...agilex_hps.core[0]
main() at /home/simicsUser/gdbDir/testGdb/testGdb.c:28
28	    int x = 1000;

In the Target Serial Console, you import the Test Application Binary testGdb and execute it, the internal GDB Server in Intel® Simics® simulator is enabled automatically. After the new-gdb-remote command, you can start the debug session in the Linux Host System.

# Target Serial Console

# Step 4. Bring the testGdb binary to the target system using TFTP, change the file permission to allow execution.
root@psgdevice:~# tftp –gr testGdb 10.10.0.1
root@psgdevice:~# chmod +x testGdb
root@psgdevice:~# ./testGdb

# Breakpoint at main() function is hit and Intel Simics simulation stops
# Next message is observed after step 6.
=== My Debug example on Core 0 ===
# Next messages are observed after step 7.
2000
  core[0]: 1 times
  core[1]: 0 times
  core[2]: 0 times
  core[3]: 0 times
 
root@psgdevice:~#

In the Linux Host System, the GDB debug session is started by using the GDB software (pre-installed in system) and the test application binary that contains the debug information.

In the GDB session, the debugger is connected to the target system using the target remote localhost:9123 command. When the connection is ready, you can start adding breakpoints or set values.

To modify the values of variable in the test application to change the program’s behavior, use the set Variable=[new value] command. In this example, setting the volatile variable exitVar to 1 sets the breaking condition to exit the infinite while loop, thus ending the program.

# Linux Host Terminal
# Step 5. Create a GDB debug session.
/home/simicsUser/gdbDir $ aarch64-none-linux-gnu-gdb testGdb
GNU gdb (GNU Toolchain for the A-profile Architecture 10.2-2020.11 
(arm-10.16)) 10.1.90.20201028-git
Copyright (C) 2020 Free Software Foundation, Inc.
(gdb)

# Step 6. Connect from the host PC to the Target System. (Use the port number 
provided by new-gdb-remote)
(gdb) target remote localhost:9123
Reading symbols from /home/simicsUser/gdbDir/testGdb/testGdb
main () at testGdb.c:26
26	    int x = 1000; 

(gdb) continue
# Type Ctrl-c to interrupt program. 
Continuing.
^C
Program received signal SIGINT, Interrupt.
getCore () at testGdb.c:9

# Step 7. The application debug starts here. Setting a breakpoint in 
getcore() function.
(gdb) break getCore
Breakpoint 2 at 0x40060c: file testGdb.c, line 13.

(gdb) continue
Continuing.
Breakpoint 2, getCore () at testGdb.c:13
13	    core = sched_getcpu();

# Go to exit point of the getCore() function.
(gdb) finish
Run till exit from #0  getCore () at testGdb.c:13
0x00000000004006a0 in main () at testGdb.c:40
40	        core = getCore();        
Value returned is $1 = 0

# Print value of exitVar variable and change it to 1 to exit loop.

(gdb) print exitVar
$2 = 0

(gdb) set exitVar=1

(gdb) print exitVar
$3 = 1

# Continue execution to finish the application.
(gdb) continue
Continuing.
[Inferior 1 (process 432) exited normally]

# Type Ctrl-c to interrupt program.
(gdb) quit