Skip to content

Latest commit

 

History

History
311 lines (220 loc) · 10.4 KB

vscode.md

File metadata and controls

311 lines (220 loc) · 10.4 KB

Intro

This document shows how to get started with using VS Code as a gdb client, which looks about like:

ares gdb server and VS Code

Prerequisites

Install gdb-multiarch

See Install gdb-multiarch.

Compiling the ROM

You need a .elf file, ideally with (at least some) debug information included.

See Compiling the ROM

If using Windows and WSL

With VS Code running in Windows, you need to provide it access to the WSL filesystem.

See Windows: WSL filesystem drive

(there are other options but this seems like the best one)

launch.json

At the root of the repo, create a folder .vscode (you may have one already), and a launch.json file inside.

You can also open a C file, go to the "Run and Debug" tab, and click "create a launch.json file".

launch.json in VS Code

launch.json in VS Code

{
    // 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": []
}

The configuration we want to add to launch.json depends on whether you're using Windows or Linux.

Windows launch.json

Add the following configuration, replacing both Z:/path/to/oot with your own (for example it may be Z:/home/YOURUSERNAME/oot).

Also change the gdb-multiarch.exe path if you installed it elsewhere, as well as the gdb server address/port [::1]:9123 if needed.

{
    "name": "GDB",
    "type": "cppdbg",
    "request": "launch",
    "program": "Z:/path/to/oot/zelda_ocarina_mq_dbg.elf",
    "cwd": "Z:/path/to/oot",
    "MIMode": "gdb",
    "miDebuggerPath": "C:/msys64/mingw64/bin/gdb-multiarch.exe",
    "miDebuggerServerAddress": "[::1]:9123",
    "miDebuggerArgs": "-readnow",
}

The full launch.json may look like:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "GDB",
            "type": "cppdbg",
            "request": "launch",
            "program": "Z:/path/to/oot/zelda_ocarina_mq_dbg.elf",
            "cwd": "Z:/path/to/oot",
            "MIMode": "gdb",
            "miDebuggerPath": "C:/msys64/mingw64/bin/gdb-multiarch.exe",
            "miDebuggerServerAddress": "[::1]:9123",
            "miDebuggerArgs": "-readnow",
        }
    ]
}

Linux launch.json

Add the following configuration:

{
    "name": "GDB",
    "type": "cppdbg",
    "request": "launch",
    "program": "${workspaceFolder}/zelda_ocarina_mq_dbg.elf",
    "cwd": "${workspaceFolder}",
    "MIMode": "gdb",
    "miDebuggerPath": "gdb-multiarch",
    "miDebuggerServerAddress": "[::1]:9123",
    "miDebuggerArgs": "-readnow",
}

The full launch.json may look like:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "GDB",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/zelda_ocarina_mq_dbg.elf",
            "cwd": "${workspaceFolder}",
            "MIMode": "gdb",
            "miDebuggerPath": "gdb-multiarch",
            "miDebuggerServerAddress": "[::1]:9123",
            "miDebuggerArgs": "-readnow",
        }
    ]
}

Additional configuration

You can add a bunch of things to the configuration. Here are some useful things:

You can add "stopAtEntry": true, to pause execution when gdb connects.

You can use "miDebuggerArgs": "...", to pass arguments to gdb-multiarch as if run on the command line. For example "miDebuggerArgs": "-readnow", passes -readnow, which makes gdb read all the debug information at once on startup.

Running

Make sure the gdb server is running already, or run it shortly after launching VS Code debugging (for example with the ares gdb server, make sure ares is open, gdb server is enabled and the ROM is loaded).

To launch the configuration we just added, go to the "Run and Debug" tab and click the green triangle "play button" near the name of the configuration "GDB".

Launch GDB in VS Code

You may also have a keyboard shortcut to run a launch configuration (F5 by default).

Once launched, the gdb client should connect to the gdb server (the ares emulator in my screenshots).

You can see it worked when the Debug toolbar (the little bar with buttons that look like "blue pause, blue arrows, green rewind, red stop", highlighted on the next screenshot) has its "pause" button enabled (that you can click).

You may also see a sign from the server that a client connected. In the case of ares, the GDB status changed to "GDB connected".

launched GDB in VS Code

If you added "stopAtEntry": true, to the configuration, the execution will be paused when gdb connects. You may also pause the execution at any time by clicking the pause icon.

When the execution pauses, the file and line corresponding to the code currently executing opens.

pausing execution in VS Code

In the side panel can also be seen the current locals and their values, as well as the current stack trace.

For more information on debugging in VS Code, see https://code.visualstudio.com/Docs/editor/debugging

Stepping

The debug toolbar allows stepping through the code:

  • the first button pauses/resumes execution.
  • the second button "step over" (dot and sideways arrow) steps by one source line, not entering functions. If a function is called on a line it is fully executed before going to the next line.
  • the third button "step into" (dot and down arrow) steps by one source line, entering functions. If a function is called the execution will pause inside that called function.
  • the fourth button "step out" (dot and up arrow) steps out of the current function, by continuing execution until the current function returns. Execution will be paused after the function returns.

The equivalents to these in the terminal gdb client are respectively ^C, c, n, s, finish.

To stop debugging, click the red stop button. The VS Code gdb client will disconnect and the game will keep running.

Breakpoints

To place a breakpoint, which pauses execution when the line it is placed on is reached, click left of the line number in a source file where you want to put the breakpoint.

placing a breakpoint in VS Code

A red dot will appear in the margin, indicating a breakpoint. Click it again to remove it.

When the breakpoint is hit, execution is paused there:

breakpoint hit in VS Code

Evaluating expressions

You can evaluate any expression, including calling functions.

One way is to add an expression to the list of watches in the side panel. Note these aren't live watches, they don't update while the game is running, they only update when the execution pauses.

Another way is to use the debug console.

The following screenshot demonstrates both options by evaluating this->pauseCtx.state and Play_GetActiveCamId(this) both ways. Note breaking on Play_Update(PlayState* this) allows to use this in the expressions.

evaluating expressions in vs code

Play_GetActiveCamId is a function without side-effects, meaning calling it does not change the state of the program. But you are not limited to only calling these functions.

For example evaluating Play_TriggerVoidOut(this) will cause a void out. Note you probably only want to make such calls in the debug console, and not in watches, so they aren't evaluated automatically every time the execution pauses.

You can also assign to data or variables. For example setting the rupee count:

gSaveContext.save.info.playerData.rupees = 69

Here is what it looks like when an expression cannot be evaluated, for example evaluating abc in a context where no such symbol exists:

abc
-var-create: unable to create variable object

Running gdb commands

You may need to run gdb commands in VS Code as if using the terminal gdb client. You can do so in the Debug Console with -exec gdbcommand.

For example -exec help:

executing gdb commands in VS Code

results in

-exec help
List of classes of commands:
...

z64 overlays

To use gdb in z64 overlays such as most actors, see GDB and z64 overlays.

Note: for running source path/to/script.py or ovl ... as explained in the linked document, don't forget to use -exec as explained above. For example -exec source path/to/script.py.

To automatically run the script when launching gdb in VS Code, add the following to your configuration in the launch.json (replacing gdb_z64overlay_load_auto.py with the proper path if needed):

"postRemoteConnectCommands": [
    {
        "text": "source gdb_z64overlay_load_auto.py"
    }
],

The full launch.json may then look like:

On Windows
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "GDB",
            "type": "cppdbg",
            "request": "launch",
            "program": "Z:/path/to/oot/zelda_ocarina_mq_dbg.elf",
            "cwd": "Z:/path/to/oot",
            "MIMode": "gdb",
            "miDebuggerPath": "C:/msys64/mingw64/bin/gdb-multiarch.exe",
            "miDebuggerServerAddress": "[::1]:9123",
            "miDebuggerArgs": "-readnow",
            "postRemoteConnectCommands": [
                {
                    "text": "source gdb_z64overlay_load_auto.py"
                }
            ],
        }
    ]
}
On Linux
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "GDB",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/zelda_ocarina_mq_dbg.elf",
            "cwd": "${workspaceFolder}",
            "MIMode": "gdb",
            "miDebuggerPath": "gdb-multiarch",
            "miDebuggerServerAddress": "[::1]:9123",
            "miDebuggerArgs": "-readnow",
            "postRemoteConnectCommands": [
                {
                    "text": "source gdb_z64overlay_load_auto.py"
                }
            ],
        }
    ]
}