Debugging with LLDB
Lemur can be used as a server for the gdb/lldb debuggers. If you're a homebrew developer, this gives you a rich source-level debugging experience for your C, C++, Rust, or assembly games. If you're reverse-engineering commercial games, it does a passable job at debugging ROMs without source code.
Setup
Setting up LLDB
To debug Virtual Boy games, you need a version of gdb or lldb built to target the Virtual Boy. The llvm-v810 compiler comes with a working version of lldb. At this time, there is no compatible version of gdb, so just use lldb.
- Download the latest llvm-v810 compiler for your OS (Windows, Darwin/Mac, or Linux). The download link is under "Assets".
- For Windows, download
llvm-v810-windows-main.7z
from the assets of a release with "Windows" in the name. - For Mac, download
llvm-v810-darwin-main.tar.xz
from the assets of a release with "Darwin" in the name. - For Linux, download
llvm-v810-linux-main.tar.xz
from the assets of a release with "Linux" in the name.
- For Windows, download
- Extract the files.
- For command-line debugging, you'll need the lldb executable from
llvm-v810/bin/lldb
(orllvm-v810/bin/lldb.exe
on Windows). - For IDE integration, you'll need the lldb-dap executable from
llvm-v810/bin/lldb-dap
(orllvm-v810/bin/lldb-dap.exe
on Windows).
- For command-line debugging, you'll need the lldb executable from
Compiling with debug info
To use source-level debugging, you must compile debug info into your game. To do this, simply add -g
to your CFLAGS
.
The -g
flag is supported in
Note that VUEngine Studio uses an older version of v810-gcc, so source-level debugging doesn't work for VUEngine games. This will be fixed Eventually™️.
This debug info will be added to your game's .elf
file, but stripped from the final .vb
file. This means compiling with -g
won't make your ROM bigger or slower.
Running the server
To run the server, you can go to "Tools > GDB Server" and click Start. It will run on port 8080 by default. You can also pass --debug-port 8080
on the command line, to run the server as soon as the app starts. Your game will be paused until the debugger connects.
Command-line debugging with lldb
You can use lldb as a command-line tool. To do this, pass your game's .elf
file to lldb, and tell it to connect to Lemur on startup:
lldb /path/to/your/game.elf -o "process connect connect://127.0.0.1:8080"
You can also run lldb without an .elf
file, but it'll be missing a lot of features (like variable inspection and call stack visualization) if you do.
lldb -o "process connect connect://127.0.0.1:8080"
At this point you can debug your game like any program. See this lldb tutorial for some examples of what you can do.
VSCode integration with lldb-dap
If your IDE has a debugger, lldb-dap lets you use it to debug your Virtual Boy game. The below instructions are for VSCode, but this will work for almost any IDE (except VUEngine Studio).
- Download the LLDB DAP extension.
- Configure the extension to use the lldb-dap you downloaded earlier. Add this to your
.vscode/settings.json
:
{
"lldb-dap.executable-path": "/path/to/llvm-v810/bin/lldb-dap"
}
- Add a launch configuration to your project. Add this to
.vscode/launch.json
:
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Debug",
"type": "lldb-dap",
"request": "launch",
"program": "${workspaceFolder}/mygame.elf", // path to your .elf file
"launchCommands": ["gdb-remote 8080"], // replace 8080 with whichever port your server uses
"preLaunchTask": "Emulate" // see step 4
}
]
}
- When you click the "Debug" button, you probably want to launch the emulator with your game. Set up a task to do this. Add this to
.vscode/tasks.json
:
{
"version": "2.0.0",
"tasks": [
{
"label": "Emulate",
"type": "shell",
"command": "/path/to/lemur",
"args": [
"${workspaceFolder}/mygame.vb", // path to your rom
"--debug-port",
"8080"
],
"isBackground": true,
"problemMatcher": {
"pattern": {
"regexp": ""
},
"background": {
"activeOnStart": true,
"beginsPattern": "Connecting",
"endsPattern": "Connecting"
}
}
}
]
}
If you're feeling spicy, you can add a "Compile" task which this "Emulate" task depends on, so that clicking "Debug" is all you need to do to start debugging.
Happy debugging!