Debug C++ code on Linux from Visual Studio

As you may have heard, Visual Studio 2015 introduces GDB support for Android development. The interesting thing about the capability is that because it debugs using GDB, it’s possible to adapt the implementation to debug other targets that support GDB debugging as well (e.g. Linux and Raspberry Pi). In this post I will share the steps I took to enable remote debugging of C++ code on Linux, Raspberry Pi.

The approach does come with some limitations as I’m adapting the implementation that was designed specifically for Android, but it shows the potential for the capability. This is a good example of why we’re open sourcing the GDB implementation itself. Note also that this is not a cross-compile solution. You’ll be working with your source files in Visual Studio, but they will be compiled on the remote Linux machine. You can trigger breakpoints and step through your source once you have things setup, which isn’t much additional work beyond getting an SSH connection properly setup.

Here are the steps

  1. Download Visual Studio 2015 RC. For the type of installation, choose Custom and select Visual C++ Mobile Development under Cross Platform Mobile Development.
  2. Download plink, putty, pscp and puttygen from the Putty download site.
  3. Set your SSH connection to your Linux installation working with cert auth. A good overview of this is the instructions for using SSH with Linux on Azure. These instructions are general enough they should cover connecting to any Linux machine from Windows, not just ones running in Azure.
  4. From your Windows machine connect to the Linux machine via Putty. You will be prompted that the servers host key is not in the registry. Select yes to add it to the registry so the host is known as trusted. If you don’t do this you will get an error later that is unclear that is the problem.
  5. You need the source you want to debug locally in a C++ Makefile project.
  6. You will need to create an xml config file that specifies where plink is, your connection info, the exe location on the remote machine and that starts gdb. Here is an example.
    <PipeLaunchOptions xmlns="http://schemas.microsoft.com/vstudio/MDDDebuggerOptions/2014"
        PipePath="plink.exe" PipeArguments="-i private.ppk user@server -batch -t gdb --interpreter=mi"
        ExePath="/home/user/YourDir/exe" ExeArguments=""
        TargetArchitecture="X64" WorkingDirectory="/home/user/YourDir" AdditionalSOLibSearchPath="">
    </PipeLaunchOptions>
  7. Open the Command window, on the Visual Studio menu, choose View -> Other Windows -> Command Window.
  8. Pass your config file via this command:
    Debug.GDBLaunch /OptionsFile:[path] /Executable:foo
  9. Enjoy remote debugging with VS2015 your C++ code on Linux!

If you want to make things a bit more streamlined, at step 5 you can specify the following as build commands in the make file project.

  • To copy your files remotely:
    pscp.exe -i private.ppk -r YourDir user@server:/home/user
  • To compile remotely:
    plink.exe user@server -i private.ppk "cd ~/YourDir; g++ -g yourcode.cpp -o yourexecutable"

Consider this a preview of things to come, here are some known issues:

  • Upon starting after step 8 above you will get an error message, “Undefined command gdb”. Our debug engine tries to start gdb once the connection is made, but we already started it via the config file parameters. If we don’t start that way the connection to GDB isn’t properly established and can leave orphan gdb processes on the target machine.
  • The first statement after entering main is missed, even if you have a breakpoint on it.
  • The parameter for Executable shouldn’t be required as the info is in the options file and the value passed isn’t used.
  • Since there is no cross compile support you need to get you toolchain and gdb setup on your Linux target machine.

Please let us know in the comments below if you find this useful or you run into any issues.  Any suggestions for improvements are also welcome.