Debugging Linux Machines Not Directly Accessible from Windows

This tutorial shows how to debug applications build with Linux cross-toolchains where the target machine is not directly accessible from the Windows machine running VisualGDB.

We will demonstrate it based on a simple setup involving 2 Linux VMs: we will build the application on ubuntu2204vm and will then deploy it to deployvm that is not directly accessible from the Windows machine.

  1. Start Visual Studio and locate the VisualGDB Linux Project Wizard:
  2. Enter the name and location for your project, then click “Create”:
  3. On the first page of the VisualGDB Linux Wizard, select “application” and choose a build system. For most new projects we recommend using Advanced CMake:
  4. The next page of the wizard allows selecting the build and deployment machines. Click “build the project under Linux” and select the build machine. If you are using a cross-toolchain, select it in the “remote toolchain” field (see this tutorial for more details). In this tutorial, the deployment machine is not accessible from the Windows side, so it won’t be listed in the “deployment computer field”:
  5. If we try adding it directly, we would get an error message (e.g. a “connection attempt failed… ” or “no such host is known”):
  6. To work around it select the build machine (ubuntu2204vm) as the deployment machine as well:
  7. If you are using a cross-toolchain that targets another CPU type (e.g. x64->ARM), the binaries produced by the toolchain won’t run on the build machine and VisualGDB will warn about it. Click “Ignore” to proceed:
  8. Finally, choose how you would like VisualGDB to manage the source files. In this tutorial we will store them on the Windows side and upload the changed files during build:
  9. Press “Finish” to create the project and build it via Build->Build Solution. Once the build succeeds, open an SSH console on the build machine (you can also use SmarTTY or any other SSH client to do it):
  10. Try connecting from the build machine to the deployment machine by running “ssh <username>@<deployment machine name> hostname” on the build machine. It should connect to the deployment machine, run “hostname” there and display its output. VisualGDB will use this mechanism to launch gdbserver on the target:
  11. Note that if running ssh on the build machine asks for password, automating it with VisualGDB won’t work. If this is the case, you would need to configure public key-based authentication between the build and deployment machines. If the build machine does not have a private SSH key generated (normally stored in ~/.ssh/id_rsa), run “ssh-keygen” on it:
  12. Install the public key matching the generated private key on the deployment machine by running “ssh-copy-id <username>@<deployment machine>” from the build machine:
  13. Now running “ssh <user name>@<deployment machine>” from the build machine should work without asking for a password:
  14. Once the SSH connections between the build and deployment machines have been configured, we can setup VisualGDB to use them to deploy and debug the built applications. First, check the “allow choosing build/clean/debug command hosts independently” checkbox on the Project Settings page of VisualGDB Project Properties:Note that this option is available on VisualGDB Custom Edition or higher.
  15. Then go to the Custom Debug Steps page and add the following step to the commands before launching the debugger:
    Command scp
    Arguments $(TargetPath) <user>@<deployment machine>:<deployment path>

    This will copy the built application to the deployment machine before VisualGDB attempts to debug it. If you would like to copy the file only when it has changed, consider using rsync instead of scp.

  16. Finally, go to the Debug Settings page and configure VisualGDB to launch gdbserver on the target indirectly and connect to it:
    Debug mode Fully custom
    GDB launch command (default)
    Use a GDB stub Yes
    GDB stub command ssh
    GDB stub arguments <user>@<deployment machine> gdbserver:<gdbserver port> <deployment path>
    Target selection command target remote <deployment machine> :<gdbserver port>

  17. Now you can debug the project as usual by pressing F5:
  18. You can double-check that the project is being built and deployed by modifying it to call the hostname() function. Verify that the host name matches the deployment machine name: