Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can i attach to a remote C++ application? #78

Closed
kevinchee opened this issue Jun 21, 2016 · 9 comments
Closed

How can i attach to a remote C++ application? #78

kevinchee opened this issue Jun 21, 2016 · 9 comments

Comments

@kevinchee
Copy link

kevinchee commented Jun 21, 2016

https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools says we can debug code locally or remotely.

I don't see how i can configure to attach to a remote application in launch.json.

Is this possible? If so, can i get help with an example of the launch.json?

@jacdavis
Copy link

Hi kevinchee. To attach to a remote application, Launch an instance of gdbserver on the target machine using an open port number. Get the target machine's ip address and set "miDebuggerServerAddress" : "ipaddress:port" in the launch.json file where ipaddress is replaced by the remote machines ip address, and port is replaced by the port you launch gdbserver with.

Then, get the process id of the remote process (using ps -e over ssh or whatever your favorite access mechanism is) and set the processId field in the launch options to that process.

@andyneff
Copy link
Contributor

@jacdavis, If I try what you said

Simple example

gdbserver localhost:6666 ./hello
{
    "name": "C++ Attach",
    "type": "cppdbg",
    "request": "attach",
    "miDebuggerServerAddress": "localhost:6666",
    "program": "${workspaceRoot}/hello",
    "processId": "13467",
    "linux": {
        "MIMode": "gdb"
    },
    "osx": {
        "MIMode": "lldb"
    },
    "windows": {
        "MIMode": "gdb"
    }
}

I get this on the gdbserver side

Process ./hello created; pid = 13467
Listening on port 6666
Remote debugging from host 127.0.0.1

and code errors out saying

Unable to start debugging. Unexpected GDB output from command "-target-attach 13467". ptrace: No such process.

Process 13467 did exist, but as soon as it connects to the gdbserver, it disconnects and stops the process

Simple workaround

However, if I use the (partially undocumented) feature processName,

{
    "name": "C++ Attach",
    "type": "cppdbg",
    "request": "attach",
    "miDebuggerServerAddress": "localhost:6666",
    "program": "${workspaceRoot}/hello",
    "processName": "hello",
    "linux": {
        "MIMode": "gdb"
    },
    "osx": {
        "MIMode": "lldb"
    },
    "windows": {
        "MIMode": "gdb"
    }
}

it does work. I'm able to set and use breakpoints

gdbserver --attach example

Also, this works

./hello & sudo gdbserver --attach localhost:6666 $!

Which is just a quick and dirty proof of using gdbserver in --attach mode (notice the sudo was necessary on my OS) and I'm able to set and use breakpoints.

Complicated gdbserver --multi

Now gdbserver --multi is typically the mode I like to operate in, but must debuggers do not support this mode.

When I try, I see a quick connect/disconnect on the gdbserver,

Unable to start debugging. Unexpected GDB output from command "-target-select remote localhost:6666". The target is not running (try extended-remote?)

Hinting to me that the gdbserver plugin (like practically ALL gdb GUIs out there) does not know to use target-select remote command. Is there a correct way to slip this in? Seeing as how there are definitely features like processName, I was wondering if there is another hidden feature to introduce some extra gdb commands.

Complicated workaround

I wrote a wrapper script for gdb (let's call it gdb2)

#!/usr/bin/env bash

exec gdb -x /tmp/gdbinit "${@}"

Used this for my launch.json

{
    "name": "C++ Attach",
    "type": "cppdbg",
    "request": "attach",
    "miDebuggerPath": "/tmp/gdb2",
    "program": "${workspaceRoot}/hello",
    "processId": "17728",
    "linux": {
        "MIMode": "gdb"
    },
    "osx": {
        "MIMode": "lldb"
    },
    "windows": {
        "MIMode": "gdb"
    }
}

And added this to my gbdinit file

target extended-remote localhost:6666
directory /my_source_code_root_dir

This time, when I run attach it asks

Superuser access is required to attach to a process. Attaching as superuser can potentially harm your computer. Do you want to continue? [y/N]

Probably because I've confused it with my wrapper script, because it doesn't know it's doing a remote attach anymore, but I say yes, and type in my password, and it attaches! And I'm able to set and use breakpoints

Question

So I was able to figure out 3 ways to get gdbserver working, but none of them were exactly what you said. Am I missing other (better) ways?

VS Code Version 1.5.3
gdb version 7.11.1
On Mint 18

@daniel-brosche
Copy link

This is my solution which works fine:

1.) run app on remote host
gdbserver localhost:4444 ./program

2.) configure launch.json for remote debugging

{
            "name": "C++ Remote Debug",
            "type": "cppdbg",
            "request": "launch",
            "miDebuggerServerAddress": "localhost:4444",
            "program": "${workspaceRoot}/build/program/program",
            "preLaunchTask": "buildDebugAndDeploy",
            "cwd": ".", 
            "linux": {
                "MIMode": "gdb"
            },
            "osx": {
                "MIMode": "lldb"
            },
            "windows": {
                "MIMode": "gdb"
            }
 }

3.) Hit F5 have FUN!

@justin-romano
Copy link

all of these examples use the localhost. Im trying to get debugging working on my orangePi but "program" cannot be resolved because it looks for this on the local computer. This dose not exist.
Is it possible. Would be a nice workflow to debug with vscode from gdbserver running remotely.

@daniel-brosche
Copy link

Actually in my tests I do attach the remote debugging session to a an application which is running in a Docker Container. Therefore it is an isolated environment which is really close to a remote debbugging session where the app runs on a target. However I have also recognized that the whole remote debugging steps arranged in tasks like: build->deploy->stop app process if still running->launch gdb server with deployed app->attach vscode debugger does not work pefect because launching the gdb server does somehow block the attachment of vscode debugger to the gdb server and the debugging does not start. When I press F5 again the vscode debugger attach to the gdbserver and the debugging starts. This is confusing... Additionaly the stopping of the remote debugging session does ofte lead to some error messages. I'm still experementing with the remote debugging capabilities of vscode with the hope to use it as my main ide for my embedded projects.

@andyneff
Copy link
Contributor

@daniel-brosche I too am mostly interested in debugging in a docker. And I can say that the portTransport feature added in 0.10.0 works great. I tried to add docker to the documentation in #568.

Both attach and launch work for me without any issue. You won't need to install ssh or gdbserver in the docker image, only gdb. The program entry in launch.json is now in the container's filesystem, and there is no need to copy the program onto your host machine. Using sourceFileMap also takes care of the difference in the filename paths between container and host.

The only gotcha is that the symbols for .so files loaded after you attach/launch are not loaded. If you need this, you should add the gdb command set auto-solib-add. An example of this looks like:

"linux": {
        "MIMode": "gdb",
        "setupCommands": [
            {
                "description": "Enable pretty-printing for gdb",
                "text": "-enable-pretty-printing",
                "ignoreFailures": true
            },
            {
                "description": "Auto load symbols when loading an .so file",
                "text": "set auto-solib-add",
                "ignoreFailures": false
            }
        ]
    },
    "osx": {
        "MIMode": "gdb",
        "setupCommands": [
            {
                "description": "Enable pretty-printing for gdb",
                "text": "-enable-pretty-printing",
                "ignoreFailures": true
            },
            {
                "description": "Auto load symbols when loading an .so file",
                "text": "set auto-solib-add",
                "ignoreFailures": false
            }
        ]
    },
    "windows": {
        "MIMode": "gdb",
        "setupCommands": [
            {
                "description": "Enable pretty-printing for gdb",
                "text": "-enable-pretty-printing",
                "ignoreFailures": true
            },
            {
                "description": "Auto load symbols when loading an .so file",
                "text": "set auto-solib-add",
                "ignoreFailures": false
            }
        ]
    }

Note: Even though the docker is running in Linux, VS Code wouldn't know this, so the MIMode and setupCommands need to be specified for the host operating system.

@andyneff
Copy link
Contributor

@justin-romano When remote debugging, you need to copy the program executable to your local machine. I recently looked at a bunch of other debuggers that support gdbserver, and they all have the same limitation. I'm not entirely sure why they all work this way, I assume things are this way because one workflow is to compile locally, push the executable to the remote system, and then run remotely. But things aren't always done that way.

I looked into using gdb -tui on a gdbserver, and this has shown me two things.

  1. You do not have to have the program locally
  2. You do not have to have the source locally

However, all the IDEs out there do not take advantage of this. It would be a nice feature request to support this though ;)

gdb/gdbserver does support a command to copy the remote program locally. I tested this idea out in a side project where I added a ${command.remoteCopyProgram} prototype. So you can start a feature request to add ${command.remoteCopyProgram} to the real vscode-cpptools or just run the gdb command yourself and copy the program locally. I think

gdb -ex 'target remote 127.0.0.1:3333' -ex 'remote get /proc/12345/exe /tmp/program'
#or if you are using: gdbserver --multi
gdb -ex 'target extended-remote 127.0.0.1:3333' -ex 'remote get /proc/12345/exe /tmp/program'

Where 127.0.0.1:3333 is your remote gdb address, 12345 is the pid you are attached to, and /tmp/program is the location on your host machine. There is no need to use the /proc/{pid}/exe trick if you already know the path on the remote machine.

Also, you might want to consider using pipeTransport introduced in version 0.10.0 and sshing into your orangePi as described here as it works so well already if you have the source locally.

@justin-romano
Copy link

Wondering if i could to this with a prelaunchTask
use ssh to copy the binaries to my host dev box. I'm already using ftp-sync to push changes from host to remote from vscode.

@yepher
Copy link

yepher commented Jan 26, 2018

With this discussion maybe VSCode should be added here: https://sourceware.org/gdb/wiki/GDB%20Front%20Ends

@github-actions github-actions bot locked and limited conversation to collaborators Oct 19, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants