Debugging the SIM Environment with VSCode
[ English | 简体中文 ]
I. Overview
This guide provides a detailed explanation of how to configure and use GDB in Visual Studio Code (VSCode) for graphical debugging of the openvela sim simulation environment. VSCode offers a modern debugging experience, including setting breakpoints, viewing the call stack, and monitoring variables and memory, which significantly enhances development and troubleshooting efficiency.
The core workflow includes:
- Environment Preparation: Install the necessary VSCode extensions.
- Project Configuration: Create and configure the
launch.jsonfile to instruct VSCode on how to start a debug session. - Debugging in Practice: Demonstrate how to start debugging, set breakpoints, and analyze the program state with a practical example.
- Advanced Topics: Address potential issues in specific scenarios, such as SMP and networking features.
II. Prerequisites
Before you begin debugging, ensure your development environment meets the following requirements.
1. Environment Requirements
- Visual Studio Code: Must be installed.
- C/C++ Extension: The core plugin from Microsoft that provides C/C++ language support and debugging capabilities in VSCode.
- Compiled
simTarget: Thesimversion of openvela must be successfully compiled, generating an executable (nuttx) that includes debugging information. The compilation must include the-gor-g3flag.
2. VSCode Environment Setup
Step 1: Install the C/C++ Extension
In the VSCode Marketplace, search for C/C++ (published by Microsoft) and click Install.
Step 2: Open the Project Workspace
Launch VSCode and use the menu File > Add Folder to Workspace... to add your openvela project root directory. This ensures that VSCode correctly resolves the ${workspaceFolder} variable in launch.json.
III. Debug Configuration (launch.json)
The launch.json file is the core configuration file for VSCode's debugging functionality. It defines how to launch and attach to your program.
1. Create launch.json
- Switch to the "Run and Debug" view in VSCode (shortcut:
Ctrl+Shift+D). - Click the "create a launch.json file" link.
- From the dropdown menu that appears, select C++ (GDB/LLDB).
- VSCode will automatically generate a
launch.jsontemplate file and save it in the.vscodefolder within your project's root directory.
2. Configure launch.json
Replace the contents of launch.json with the following configuration. This configuration is specifically tailored for debugging the openvela sim environment.
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug openvela (sim)",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/nuttx/nuttx",
"stopAtEntry": false,
"cwd": "${workspaceFolder}/nuttx",
"environment": [],
"console": "externalTerminal",
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}
Configuration Parameter Breakdown
| Attribute | Value | Description |
|---|---|---|
name |
Debug openvela (sim) |
The name of the debug configuration, which appears in the VSCode debug dropdown menu. |
type |
cppdbg |
Specifies using the C/C++ extension for debugging. |
request |
launch |
Indicates a launch type session, where VSCode is responsible for starting the program. |
program |
${workspaceFolder}/nuttx/nuttx |
Key Parameter. Specifies the path to the executable file to be debugged. ${workspaceFolder} represents the root directory of the project you have open in VSCode. |
stopAtEntry |
false |
If set to true, the program will automatically pause at the entry point (e.g., _start).It is usually set to false to let the program run directly to your set breakpoints. |
cwd |
${workspaceFolder}/nuttx |
Sets the working directory for the program being debugged. For the sim environment, this is typically the directory containing the nuttx executable. |
console |
externalTerminal |
Specifies running the program in an external terminal. This is crucial for the sim environment, which requires interaction with the NuttShell (NSH), as you can input commands in this terminal. |
MIMode |
gdb |
Specifies GDB as the debugger backend. |
setupCommands |
[...] |
Commands to be executed after GDB starts but before the program runs. By default, this enables 'pretty-printing' to display complex data structures like STL in a more readable format. |
IV. Debugging in Practice
Next, we will walk through the entire process using the ping command as an example.
Step 1: Open Source Code and Set a Breakpoint
In VSCode, open the file apps/system/ping/ping.c. At the entry of the ping_main function (or any line you are interested in), click in the margin to the left of the line number to set a red dot breakpoint.
Step 2: Start the Debug Session
Press F5 or click the green start button in the "Run and Debug" view. VSCode will:
- Launch GDB.
- Open a new external terminal window.
- Run the
nuttxprogram in that terminal, where you will see the NSH startup promptnsh>.
Step 3: Trigger the Breakpoint
In the external terminal where the nsh> prompt is displayed, enter the command to trigger the breakpoint:
nsh> ping 127.0.0.1
Step 4: Analyze the Program State
When the program execution reaches ping_main, you will see:
- The VSCode window automatically gains focus.
- The line with the breakpoint is highlighted in the code editor.
- The debug panel on the left is populated with real-time information:
- VARIABLES: Displays the values of local and global variables in the current scope.
- WATCH: Allows you to add expressions to continuously monitor their values.
- CALL STACK: Clearly shows the function call stack, helping you understand the program's execution path.
- BREAKPOINTS: Manages all the breakpoints you have set.
V. Advanced Topics and FAQ
1. Handling the SIGUSR1 Signal in SMP Debugging
Symptom
If your openvela configuration has Symmetric Multiprocessing (SMP) enabled, the program might unexpectedly pause due to a SIGUSR1 signal shortly after starting a debug session.
Cause Analysis
In SMP mode, openvela uses the SIGUSR1 signal for inter-core task scheduling and communication. By default, GDB intercepts all signals and pauses the program, which interferes with the system's normal operation.
Solution
You can instruct GDB to ignore this signal by creating a global GDB initialization script.
-
Create a file:
~/.gdbinit(located in your user home directory). -
Add the following command to the file:
# Instruct GDB to not stop or print a message for SIGUSR1 handle SIGUSR1 nostop noprint -
Save the file. GDB will automatically load and execute the commands in this file every time it starts, thus resolving the issue.
2. Acquiring Root Privileges for sim
Scenario
Certain advanced features of the sim environment, especially those related to networking (like using a TAP device to communicate with the host system), require root privileges to function correctly. Directly using sudo F5 is not feasible.
Solution
The recommended approach is to configure sudo to allow your user account to run gdb as root without a password.
-
Configure passwordless
sudo.For security and best practice, we will create a dedicated configuration file in the
/etc/sudoers.d/directory. This method is safer than directly modifying the mainsudoersfile.Execute the following command in your Linux terminal, replacing
your_usernamewith your actual username:# Replace your_username with your actual username echo "your_username ALL=(ALL) NOPASSWD: /usr/bin/gdb" | sudo tee /etc/sudoers.d/gdb-nopasswd -
Create a GDB wrapper script.
In your project's root directory (for example,
openvela/), create a file namedsudo-gdb.shand add the following content:#!/bin/bash # This script acts as a wrapper to launch gdb with sudo. sudo /usr/bin/gdb "$@"Then, grant the script execute permissions:
chmod +x sudo-gdb.sh -
Modify
launch.json.Modify the
.vscode/launch.jsonfile by adding the"miDebuggerPath"property to your debug configuration, pointing it to the script we just created.{ "name": "Debug openvela (sim) with Root", "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/nuttx/nuttx", "miDebuggerPath": "${workspaceFolder}/sudo-gdb.sh", // <-- Add this line "stopAtEntry": false, "cwd": "${workspaceFolder}/nuttx", "environment": [], "console": "externalTerminal", "MIMode": "gdb", "setupCommands": [ { "description": "Enable pretty-printing for gdb", "text": "-enable-pretty-printing", "ignoreFailures": true } ] }
After completing these steps, select the new debug configuration and press F5 to start. Your sim program will now run with root privileges.