VS Code Setup

VS Code Extensions

You don’t need any of Microsofts Remote Development extensions. Those are for working with source code that’s on another machine.

The extensions you need are

You may be thinking “Why LLDB? I thought we were using GDB?”. GDB is essentially a hack and LLDB just happens to be compatible with that hack so, for our purposes, it’s essentially the same thing.

  1. rust-analyzer (rust-lang.rust-analyzer)
  2. CodeLLDB (vadimcn.vscode-lldb)

Tasks

First you’ll need commands which will build your program. Inside the project this is the file .vscode/tasks.json:

The field label is the unique identifier for each, which is how dependency chains are handled in VS Code. The six arguments match up with the script below.

{
  "version": "2.0.0",
    "tasks": 
  [
    {
      "label": "cargo: build for aarch64",
      "type": "shell",
      "command": "cargo",
      "args": 
      [
        "build",
        "--target=aarch64-unknown-linux-gnu"
      ],

      "problemMatcher": 
      [
        "$rustc"
      ],

      "group":
      {
        "kind": "build",
        "isDefault": false
      }
    },


    
    {
      "label": "gdbserver: setup on remote",
      "type": "shell",
      "command": "${workspaceFolder}/gdbserver-setup.sh",
       
      "args":
      [
          "${workspaceFolder}",         // WS_FOLDER
          "rust-proj",                  // APP_NAME
          "user",                       // REMOTE_USER
          "10.23.34.62",                // REMOTE_HOST
          "aarch64-unknown-linux-gnu",  // REMOTE_ARCH
          "2000"                        // GDB_PORT
      ],

      "group": 
      {
        "kind": "build",
        "isDefault": false
      },
      
      "dependsOn":
      [
        "cargo: build for aarch64",
      ],
    },
  ]
}

GDB Server Launcher Script

The script below is called on line 32 and should be saved as gdbserver-setup.sh in the root of your project folder. Don’t forget to do chmod u+x on it1 or you’ll get permission denied errors.

1 I may have been stuck on this point a little longer than I’m comfortable admitting.

#!/bin/bash

# Exit immediately if some variables are unset
set -o nounset
# Enable verbose tracing for debug purposes
set -o xtrace
WS_FOLDER="$1"
BIN_NAME="$2"
REMOTE_USER="$3"
REMOTE_HOST="$4"
REMOTE_ARCH="$5"
GDB_PORT="$6"

# Set target path
REMOTE_PATH="/home/${REMOTE_USER}/bin/debug"

# Set binary path to upload
BIN_PATH="${WS_FOLDER}/target/${REMOTE_ARCH}/debug/${BIN_NAME}"
# Kill previous debug sessions
ssh "${REMOTE_USER}@${REMOTE_HOST}" "killall gdbserver ${BIN_NAME}"
# Secure copy to the target device
scp "${BIN_PATH}" "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PATH}"
# Start remote debug session
ssh -f "${REMOTE_USER}@${REMOTE_HOST}" "sh -c 'cd ${REMOTE_PATH}; nohup gdbserver :${GDB_PORT} ./${BIN_NAME} > ./console.log 2>&1 &'"

From line 14 and 17 you may notice that there are som directories that need to exist on the remote:

$ mkdir -p bin/debug

Launchers

This is the file .vscode/launch.json:

{
  "version": "0.2.0",
  "configurations":
  [
    {
      "type": "lldb",
      "request": "launch",
      "name": "Debug executable 'rust-proj'",
      "cargo":
      {
        "args":
        [
          "build",
          "--bin=rust-proj",
          "--package=rust-proj"
        ],

        "filter":
        {
          "name": "rust-proj",
          "kind": "bin"
        }
      },
      "args": [],
      "cwd": "${workspaceFolder}"
    },


    {
      "type": "lldb",
      "request": "launch",
      "name": "Debug unit tests in executable 'rust-proj'",
      "cargo":
      {
        "args":
        [
          "test",
          "--no-run",
          "--bin=rust-proj",
          "--package=rust-proj"
        ],
        "filter":
        {
          "name": "rust-proj",
          "kind": "bin"
        }
      },
      "args": [],
      "cwd": "${workspaceFolder}"
    },

    // Below is the part that we'll use for remote debug
    {
      "type": "lldb",
      "request": "custom",
      "name": "Embedded Linux Remote Debug",
      "preLaunchTask": "gdbserver: setup on remote",
      "targetCreateCommands": ["target create ${workspaceFolder}/target/aarch64-unknown-linux-gnu/debug/rust-proj"],
      "processCreateCommands": ["gdb-remote 10.23.34.62:2000"]
    }
  ]
}

Making Things Simpler

It can be quite annoying to have to enter the the remotes password three times for every debug session.

To get around this, use the command ssh-copy-id to install your public key onto the remote machine:

$ ssh-copy-id user@10.23.34.62

As it’s said in the picture, try logging in to the machine with ssh again. If it all worked out you should no longer need to input the password each time.

Leaving comments

If something isn’t working as stated or there are some other errors, don’t hesitate to report it HERE.