bazel-contrib / rules_go

Go rules for Bazel
Apache License 2.0
1.38k stars 659 forks source link

Unable to debug using delve in VS Code #1844

Open smukherj1 opened 5 years ago

smukherj1 commented 5 years ago

I built my go binary using rules_go and gazelle. I'm using VS Code as my editor and using a launch configuration with mode "exec". I built my code using bazel build --strip=never -c dbg.

When I launch the debugger using "F5" in VS Code, my breakpoints aren't hit. However, when I launch "dlv" manually over the command line using "dlv exec /path/to/binary", it runs fine and hits my breakpoints.

smukherj1 commented 5 years ago

@jayconrod Been looking at this in the background a little more and I found the underlying issue is that VS Code is passing absolute paths to delve which delve is rejecting. I turned on verbose logging in the VS Code debug launch.json by adding

"trace": "verbose"

and I saw the following in the debug output

Error on CreateBreakpoint: could not find /usr/local/google/home/suvanjan/repos/gob/toolchain/src/experimental/composable_layers/layer_extractor/cmd/layer_extractor.go:60

Sure enough, I launched delve from the command line and when I try to do

b /usr/local/google/home/suvanjan/repos/gob/toolchain/src/experimental/composable_layers/layer_extractor/cmd/layer_extractor.go:60

Delve fails to set the breakpoint as well. However, it works when I give delve a path relative to the directory delve was launched from.

The VS Code go extension is generating the path here https://github.com/Microsoft/vscode-go/blob/2bd8c4f566eade53a935d85dbeeedc430b614b5f/src/debugAdapter/goDebug.ts#L677 which is calling https://github.com/Microsoft/vscode-debugadapter-node/blob/64665fe18a0316b2a871df4b36cff214c28d2598/adapter/src/debugSession.ts#L781 which seems to simply returns the absolute path.

I wonder if this is actually a limitation in delve where it always adds the working directory to the beginning of file locations even if the file location was absolute?

smukherj1 commented 5 years ago

Confirmed https://github.com/derekparker/delve/blob/34e802a42b9dc3ba3c4a513b50e9eec6afedcdf2/service/debugger/locations.go#L268 is the relevant code in delve that attempts to resolve the file path:line to a PC address.

However, for absolute paths, the "scope.EvalExpression" rejects the expression with the error "expected operand, found '/'". It works when I do just filename.go:lineno

Seems like the issue would need to be resolved between the VS Code go extension and delve

kabriel commented 3 years ago

I'm hitting this issue as well, has anyone made progress?

dk185217 commented 2 years ago

Not sure if this will still be useful to you but...

I was having a similar issue. I built a binary with bazel, exec'ed it with dlv, but was unable to stop at breakpoints in vscode. I believe it is solved with substitutePath, although im not sure why.

First, I build and exec dlv with something like:

#!/usr/bin/env bash
target=$1
bazel build --strip=never -c dbg "${target}"
outs=$(bazel cquery --strip=never -c dbg --output=files "${target}")
n=${#outs[@]}
if [[ "$n" -gt 1 ]]; then
  echo "too many outputs, not sure which one to debug (is this necessary?)"
fi
command="${outs[0]}"
dlv exec "${command}" --log --log-output=dap --headless --listen=127.0.0.1:50034 --api-version=2

For that, you need bazel 5.3-ish, for the --output=files cquery option

Then, I start debug in vscode with this launch configuration:

{
            "name": "connect to dlv",
            "type": "go",
            "debugAdapter": "dlv-dap", // `legacy` by default
            "request": "attach",
            "mode": "remote",
            "port": 50034,
            "host": "127.0.0.1", // can skip for localhost
            "logOutput": "dap",
            "showLog": true,
            "trace": "verbose",
            "substitutePath": [
              { "from": "${workspaceFolder}", "to": "" }
          ]
        }

which I got from https://github.com/golang/vscode-go/wiki/debugging#connecting-to-headless-delve-with-target-specified-at-server-start-up

The important part seems to be "stripping" the workspaceFolder by replacing with "". I was originally seeing a message in the dlv logs that said:

"message":"could not find file /Users/<me>/dev/<org>/<repo>/cmd/<foo>/main.go"

which seems odd, because its absolute, has no links, is the correct path etc, but nevertheless, I tried a few different substitutePath options based on other answers floating around, and what I pasted above is what ultimately ended up working for me.

balakumarsubramani commented 4 months ago

I ended up following @dk185217's recommendation. In mycase ${workspaceFolder} was not an exact match, it was a subpath. If you're on the same boat, after starting the dlv server, attach to it and find the path in binary with below commands.

# dlv connect <addr>
(dlv) sources filename.go
real/path/filename.go
(dlv)