Skip to content
This repository has been archived by the owner on Jul 15, 2023. It is now read-only.

Can't set breakpoint in vscode under windows when remote debugging linux-proccess under linux with delve #2931

Closed
deschmih opened this issue Dec 6, 2019 · 9 comments
Labels

Comments

@deschmih
Copy link

deschmih commented Dec 6, 2019

What version of Go, VS Code & VS Code Go extension are you using?

  • Run go version to get version of Go
    • go version go1.13.4 windows/amd64
  • Run code -v or code-insiders -v to get version of VS Code or VS Code Insiders
    • Version: 1.40.2
  • Check your installed extensions to get the version of the VS Code Go extension
    • v 0.11.9
  • Run go env GOOS GOARCH to get the operating system and processor arhcitecture details
    • linux amd64 --> was set manually under windows 10 via go env -w GOOS=linux

Share the Go related settings you have added/edited

Run Preferences: Open Settings (JSON) command to open your settings.json file.
Share all the settings with the go. or ["go"] prefixes.

  • "go.autocompleteUnimportedPackages": true,
  • "go.formatTool": "goimports",
  • "go.useLanguageServer": true,

Describe the bug

Vscode runs under windows 10 and i compile a hello.go (simple hello world) for linux with GOOS=linux.

Simple hello world:

package main

import (
	"fmt"
	"time"
)

func main() {
	for {
		time.Sleep(time.Second)
		fmt.Println("tick")
		time.Sleep(time.Second)
		fmt.Println("tack")
	}
}

The binary is copied to linux and delve is run to make a connection from vscode to remote linux server. My launch-configuration for this connection under vscode is:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Connect to server",
            "type": "go",
            "request": "attach",
            "mode": "remote",
            "remotePath": "c:/gopath/src/hello",
            "port": 2000,
            "host": "10.1.99.83",
            "logOutput": "rpc",
            "showLog": true,
            "trace": "log",
       },
    ]
}

Remote connection to delve is successful but setting a break-point fails.

Dlv log on linux server:

root@epu-sewlabor1:/data/epu/hello# /home/epu/dlv exec ./hello -l 10.1.99.83:2000 --headless --api-version 2 --log=true --log-output=debugger,debuglineerr,gdbwire,lldbout,rpc
API server listening at: 10.1.99.83:2000
2019-12-06T13:06:12Z info layer=debugger launching process with args: [./hello]
2019-12-06T13:06:28Z debug layer=rpc <- RPCServer.GetVersion(api.GetVersionIn{})
2019-12-06T13:06:28Z debug layer=rpc -> *api.GetVersionOut{"DelveVersion":"Version: 1.3.2\nBuild: $Id: 569ccbd514fc47c8b4c521b142556867ec5e6917 $","APIVersion":2,"Backend":"native"} error: ""
2019-12-06T13:06:28Z debug layer=rpc <- RPCServer.State(rpc2.StateIn{"NonBlocking":true})
2019-12-06T13:06:28Z debug layer=rpc -> *rpc2.StateOut{"State":{"Running":false,"currentThread":{"id":21266,"pc":4542608,"file":"c:/go/src/runtime/rt0_linux_amd64.s","line":8,"function":{"name":"_rt0_amd64_linux","value":4542608,"type":0,"goType":0,"optimized":true},"goroutineID":0,"ReturnValues":null},"Threads":[{"id":21266,"pc":4542608,"file":"c:/go/src/runtime/rt0_linux_amd64.s","line":8,"function":{"name":"_rt0_amd64_linux","value":4542608,"type":0,"goType":0,"optimized":true},"goroutineID":0,"ReturnValues":null}],"NextInProgress":false,"exited":false,"exitStatus":0,"When":""}} error: ""
2019-12-06T13:06:28Z debug layer=rpc <- RPCServer.CreateBreakpoint(rpc2.CreateBreakpointIn{"Breakpoint":{"id":0,"name":"","addr":0,"file":"c:\\gopath\\src\\hello\\hello.go","line":11,"Cond":"","continue":false,"traceReturn":false,"goroutine":false,"stacktrace":0,"LoadArgs":{"FollowPointers":true,"MaxVariableRecurse":1,"MaxStringLen":64,"MaxArrayValues":64,"MaxStructFields":-1},"LoadLocals":{"FollowPointers":true,"MaxVariableRecurse":1,"MaxStringLen":64,"MaxArrayValues":64,"MaxStructFields":-1},"hitCount":null,"totalHitCount":0}})
2019-12-06T13:06:28Z debug layer=rpc -> *rpc2.CreateBreakpointOut{"Breakpoint":{"id":0,"name":"","addr":0,"file":"","line":0,"Cond":"","continue":false,"traceReturn":false,"goroutine":false,"stacktrace":0,"LoadArgs":null,"LoadLocals":null,"hitCount":null,"totalHitCount":0}} error: "could not find file c:\\gopath\\src\\hello\\hello.go"
2019-12-06T13:06:28Z debug layer=rpc <- RPCServer.State(rpc2.StateIn{"NonBlocking":true})
2019-12-06T13:06:28Z debug layer=rpc -> *rpc2.StateOut{"State":{"Running":false,"currentThread":{"id":21266,"pc":4542608,"file":"c:/go/src/runtime/rt0_linux_amd64.s","line":8,"function":{"name":"_rt0_amd64_linux","value":4542608,"type":0,"goType":0,"optimized":true},"goroutineID":0,"ReturnValues":null},"Threads":[{"id":21266,"pc":4542608,"file":"c:/go/src/runtime/rt0_linux_amd64.s","line":8,"function":{"name":"_rt0_amd64_linux","value":4542608,"type":0,"goType":0,"optimized":true},"goroutineID":0,"ReturnValues":null}],"NextInProgress":false,"exited":false,"exitStatus":0,"When":""}} error: ""
2019-12-06T13:06:28Z debug layer=rpc (async 5) <- RPCServer.Command(api.DebuggerCommand{"name":"continue","ReturnInfoLoadConfig":null})
2019-12-06T13:06:28Z debug layer=debugger continuing
tick
tack
tick
tack
tick
tack
2019-12-06T13:06:35Z debug layer=rpc <- RPCServer.State(rpc2.StateIn{"NonBlocking":true})
2019-12-06T13:06:35Z debug layer=rpc -> *rpc2.StateOut{"State":{"Running":true,"Threads":null,"NextInProgress":false,"exited":false,"exitStatus":0,"When":""}} error: ""
2019-12-06T13:06:35Z debug layer=rpc (async 7) <- RPCServer.Command(api.DebuggerCommand{"name":"halt","ReturnInfoLoadConfig":null})
2019-12-06T13:06:35Z debug layer=debugger halting
2019-12-06T13:06:35Z debug layer=rpc (async 5) -> rpc2.CommandOut{"State":{"Running":false,"currentThread":{"id":21266,"pc":4544339,"file":"c:/go/src/runtime/sys_linux_amd64.s","line":536,"function":{"name":"runtime.futex","value":4544304,"type":0,"goType":0,"optimized":true},"goroutineID":33,"ReturnValues":null},"currentGoroutine":{"id":33,"currentLoc":{"pc":4544339,"file":"c:/go/src/runtime/sys_linux_amd64.s","line":536,"function":{"name":"runtime.futex","value":4544304,"type":0,"goType":0,"optimized":true}},"userCurrentLoc":{"pc":4544339,"file":"c:/go/src/runtime/sys_linux_amd64.s","line":536,"function":{"name":"runtime.futex","value":4544304,"type":0,"goType":0,"optimized":true}},"goStatementLoc":{"pc":4475310,"file":"c:/go/src/runtime/time.go","line":169,"function":{"name":"runtime.(*timersBucket).addtimerLocked","value":4475040,"type":0,"goType":0,"optimized":true}},"startLoc":{"pc":4476160,"file":"c:/go/src/runtime/time.go","line":247,"function":{"name":"runtime.timerproc","value":4476160,"type":0,"goType":0,"optimized":true}},"threadID":21266,"unreadable":""},"Threads":[{"id":21266,"pc":4544339,"file":"c:/go/src/runtime/sys_linux_amd64.s","line":536,"function":{"name":"runtime.futex","value":4544304,"type":0,"goType":0,"optimized":true},"goroutineID":33,"ReturnValues":null},{"id":21632,"pc":4544339,"file":"c:/go/src/runtime/sys_linux_amd64.s","line":536,"function":{"name":"runtime.futex","value":4544304,"type":0,"goType":0,"optimized":true},"goroutineID":0,"ReturnValues":null},{"id":21633,"pc":4544339,"file":"c:/go/src/runtime/sys_linux_amd64.s","line":536,"function":{"name":"runtime.futex","value":4544304,"type":0,"goType":0,"optimized":true},"goroutineID":0,"ReturnValues":null},{"id":21635,"pc":4544339,"file":"c:/go/src/runtime/sys_linux_amd64.s","line":536,"function":{"name":"runtime.futex","value":4544304,"type":0,"goType":0,"optimized":true},"goroutineID":0,"ReturnValues":null},{"id":21634,"pc":4544339,"file":"c:/go/src/runtime/sys_linux_amd64.s","line":536,"function":{"name":"runtime.futex","value":4544304,"type":0,"goType":0,"optimized":true},"goroutineID":0,"ReturnValues":null}],"NextInProgress":false,"exited":false,"exitStatus":0,"When":""}} error: ""
2019-12-06T13:06:35Z debug layer=rpc <- RPCServer.ListGoroutines(rpc2.ListGoroutinesIn{"Start":0,"Count":0})
2019-12-06T13:06:35Z debug layer=rpc (async 7) -> rpc2.CommandOut{"State":{"Running":false,"currentThread":{"id":21266,"pc":4544339,"file":"c:/go/src/runtime/sys_linux_amd64.s","line":536,"function":{"name":"runtime.futex","value":4544304,"type":0,"goType":0,"optimized":true},"goroutineID":33,"ReturnValues":null},"currentGoroutine":{"id":33,"currentLoc":{"pc":4544339,"file":"c:/go/src/runtime/sys_linux_amd64.s","line":536,"function":{"name":"runtime.futex","value":4544304,"type":0,"goType":0,"optimized":true}},"userCurrentLoc":{"pc":4544339,"file":"c:/go/src/runtime/sys_linux_amd64.s","line":536,"function":{"name":"runtime.futex","value":4544304,"type":0,"goType":0,"optimized":true}},"goStatementLoc":{"pc":4475310,"file":"c:/go/src/runtime/time.go","line":169,"function":{"name":"runtime.(*timersBucket).addtimerLocked","value":4475040,"type":0,"goType":0,"optimized":true}},"startLoc":{"pc":4476160,"file":"c:/go/src/runtime/time.go","line":247,"function":{"name":"runtime.timerproc","value":4476160,"type":0,"goType":0,"optimized":true}},"threadID":21266,"unreadable":""},"Threads":[{"id":21635,"pc":4544339,"file":"c:/go/src/runtime/sys_linux_amd64.s","line":536,"function":{"name":"runtime.futex","value":4544304,"type":0,"goType":0,"optimized":true},"goroutineID":0,"ReturnValues":null},{"id":21634,"pc":4544339,"file":"c:/go/src/runtime/sys_linux_amd64.s","line":536,"function":{"name":"runtime.futex","value":4544304,"type":0,"goType":0,"optimized":true},"goroutineID":0,"ReturnValues":null},{"id":21266,"pc":4544339,"file":"c:/go/src/runtime/sys_linux_amd64.s","line":536,"function":{"name":"runtime.futex","value":4544304,"type":0,"goType":0,"optimized":true},"goroutineID":33,"ReturnValues":null},{"id":21632,"pc":4544339,"file":"c:/go/src/runtime/sys_linux_amd64.s","line":536,"function":{"name":"runtime.futex","value":4544304,"type":0,"goType":0,"optimized":true},"goroutineID":0,"ReturnValues":null},{"id":21633,"pc":4544339,"file":"c:/go/src/runtime/sys_linux_amd64.s","line":536,"function":{"name":"runtime.futex","value":4544304,"type":0,"goType":0,"optimized":true},"goroutineID":0,"ReturnValues":null}],"NextInProgress":false,"exited":false,"exitStatus":0,"When":""}} error: ""
2019-12-06T13:06:35Z debug layer=rpc -> *rpc2.ListGoroutinesOut{"Goroutines":[{"id":1,"currentLoc":{"pc":4371744,"file":"c:/go/src/runtime/proc.go","line":305,"function":{"name":"runtime.gopark","value":4371520,"type":0,"goType":0,"optimized":true}},"userCurrentLoc":{"pc":4474455,"file":"c:/go/src/runtime/proc.go","line":310,"function":{"name":"time.Sleep","value":4474112,"type":0,"goType":0,"optimized":true}},"goStatementLoc":{"pc":4528132,"file":"c:/go/src/runtime/asm_amd64.s","line":220,"function":{"name":"runtime.rt0_go","value":4527824,"type":0,"goType":0,"optimized":true}},"startLoc":{"pc":4370240,"file":"c:/go/src/runtime/proc.go","line":113,"function":{"name":"runtime.main","value":4370240,"type":0,"goType":0,"optimized":true}},"threadID":0,"unreadable":""},{"id":2,"currentLoc":{"pc":4371744,"file":"c:/go/src/runtime/proc.go","line":305,"function":{"name":"runtime.gopark","value":4371520,"type":0,"goType":0,"optimized":true}},"userCurrentLoc":{"pc":4371744,"file":"c:/go/src/runtime/proc.go","line":305,"function":{"name":"runtime.gopark","value":4371520,"type":0,"goType":0,"optimized":true}},"goStatementLoc":{"pc":4371205,"file":"c:/go/src/runtime/proc.go","line":242,"function":{"name":"runtime.init.5","value":4371152,"type":0,"goType":0,"optimized":true}},"startLoc":{"pc":4371232,"file":"c:/go/src/runtime/proc.go","line":245,"function":{"name":"runtime.forcegchelper","value":4371232,"type":0,"goType":0,"optimized":true}},"threadID":0,"unreadable":""},{"id":3,"currentLoc":{"pc":4371744,"file":"c:/go/src/runtime/proc.go","line":305,"function":{"name":"runtime.gopark","value":4371520,"type":0,"goType":0,"optimized":true}},"userCurrentLoc":{"pc":4371744,"file":"c:/go/src/runtime/proc.go","line":305,"function":{"name":"runtime.gopark","value":4371520,"type":0,"goType":0,"optimized":true}},"goStatementLoc":{"pc":4284172,"file":"c:/go/src/runtime/mgc.go","line":210,"function":{"name":"runtime.gcenable","value":4284080,"type":0,"goType":0,"optimized":true}},"startLoc":{"pc":4321040,"file":"c:/go/src/runtime/mgcsweep.go","line":64,"function":{"name":"runtime.bgsweep","value":4321040,"type":0,"goType":0,"optimized":true}},"threadID":0,"unreadable":""},{"id":4,"currentLoc":{"pc":4371744,"file":"c:/go/src/runtime/proc.go","line":305,"function":{"name":"runtime.gopark","value":4371520,"type":0,"goType":0,"optimized":true}},"userCurrentLoc":{"pc":4371744,"file":"c:/go/src/runtime/proc.go","line":305,"function":{"name":"runtime.gopark","value":4371520,"type":0,"goType":0,"optimized":true}},"goStatementLoc":{"pc":4284206,"file":"c:/go/src/runtime/mgc.go","line":211,"function":{"name":"runtime.gcenable","value":4284080,"type":0,"goType":0,"optimized":true}},"startLoc":{"pc":4318544,"file":"c:/go/src/runtime/mgcscavenge.go","line":287,"function":{"name":"runtime.bgscavenge","value":4318544,"type":0,"goType":0,"optimized":true}},"threadID":0,"unreadable":""},{"id":5,"currentLoc":{"pc":4371744,"file":"c:/go/src/runtime/proc.go","line":305,"function":{"name":"runtime.gopark","value":4371520,"type":0,"goType":0,"optimized":true}},"userCurrentLoc":{"pc":4371744,"file":"c:/go/src/runtime/proc.go","line":305,"function":{"name":"runtime.gopark","value":4371520,"type":0,"goType":0,"optimized":true}},"goStatementLoc":{"pc":4280161,"file":"c:/go/src/runtime/mfinal.go","line":156,"function":{"name":"runtime.createfing","value":4280064,"type":0,"goType":0,"optimized":true}},"startLoc":{"pc":4280176,"file":"c:/go/src/runtime/mfinal.go","line":161,"function":{"name":"runtime.runfinq","value":4280176,"type":0,"goType":0,"optimized":true}},"threadID":0,"unreadable":""},{"id":6,"currentLoc":{"pc":4371744,"file":"c:/go/src/runtime/proc.go","line":305,"function":{"name":"runtime.gopark","value":4371520,"type":0,"goType":0,"optimized":true}},"userCurrentLoc":{"pc":4371744,"file":"c:/go/src/runtime/proc.go","line":305,"function":{"name":"runtime.gopark","value":4371520,"type":0,"goType":0,"optimized":true}},"goStatementLoc":{"pc":4475310,"file":"c:/go/src/runtime/time.go","line":169,"function":{"name":"runtime.(*timersBucket).addtimerLocked","value":4475040,"type":0,"goType":0,"optimized":true}},"startLoc":{"pc":4476160,"file":"c:/go/src/runtime/time.go","line":247,"function":{"name":"runtime.timerproc","value":4476160,"type":0,"goType":0,"optimized":true}},"threadID":0,"unreadable":""},{"id":17,"currentLoc":{"pc":4371744,"file":"c:/go/src/runtime/proc.go","line":305,"function":{"name":"runtime.gopark","value":4371520,"type":0,"goType":0,"optimized":true}},"userCurrentLoc":{"pc":4371744,"file":"c:/go/src/runtime/proc.go","line":305,"function":{"name":"runtime.gopark","value":4371520,"type":0,"goType":0,"optimized":true}},"goStatementLoc":{"pc":4475310,"file":"c:/go/src/runtime/time.go","line":169,"function":{"name":"runtime.(*timersBucket).addtimerLocked","value":4475040,"type":0,"goType":0,"optimized":true}},"startLoc":{"pc":4476160,"file":"c:/go/src/runtime/time.go","line":247,"function":{"name":"runtime.timerproc","value":4476160,"type":0,"goType":0,"optimized":true}},"threadID":0,"unreadable":""},{"id":33,"currentLoc":{"pc":4234500,"file":"c:/go/src/runtime/lock_futex.go","line":228,"function":{"name":"runtime.notetsleepg","value":4234448,"type":0,"goType":0,"optimized":true}},"userCurrentLoc":{"pc":4234500,"file":"c:/go/src/runtime/lock_futex.go","line":228,"function":{"name":"runtime.notetsleepg","value":4234448,"type":0,"goType":0,"optimized":true}},"goStatementLoc":{"pc":4475310,"file":"c:/go/src/runtime/time.go","line":169,"function":{"name":"runtime.(*timersBucket).addtimerLocked","value":4475040,"type":0,"goType":0,"optimized":true}},"startLoc":{"pc":4476160,"file":"c:/go/src/runtime/time.go","line":247,"function":{"name":"runtime.timerproc","value":4476160,"type":0,"goType":0,"optimized":true}},"threadID":0,"unreadable":""}],"Nextg":-1} error: ""
2019-12-06T13:06:35Z debug layer=rpc (async 9) <- RPCServer.Command(api.DebuggerCommand{"name":"continue","ReturnInfoLoadConfig":null})
2019-12-06T13:06:35Z debug layer=debugger continuing
tick
tack
tick
tack
2019-12-06T13:06:39Z debug layer=rpc (async 9) -> rpc2.CommandOut{"State":{"Running":false,"Threads":null,"NextInProgress":false,"exited":true,"exitStatus":0,"When":""}} error: ""
2019-12-06T13:06:39Z debug layer=rpc <- RPCServer.State(rpc2.StateIn{"NonBlocking":true})
2019-12-06T13:06:39Z debug layer=rpc -> *rpc2.StateOut{"State":null} error: "Process 21266 has exited with status 0"
2019-12-06T13:06:40Z error layer=rpc rpc:read tcp 10.1.99.83:2000->10.1.98.107:52277: read: connection reset by peer

The log shows the problem. In the binary, build on windows for linux, the path for hello.go is set to c:/gopath/src/hello/hello.go. During the rpc-call for CreateBreakpoint from vscode to dlv the file c:\\gopath\\src\\hello\\hello.go is used.
Dlv does not find the correct file for set an breakpoint, because of the differently used pathseperators.

objdump hello:
here you can see path "c:/gopath/src/hello/hello.go"

$  go tool objdump hello | grep hello.go                                                         
TEXT main.main(SB) c:/gopath/src/hello/hello.go                                                  
  hello.go:8            0x48d160                64488b0c25f8ffffff      MOVQ FS:0xfffffff8, CX   
...

Workaround and test:

  • Build hello.go with go build -gcflags=-trimpath=c: -asmflags=-trimpath=c: and update the binary on linux server.
  • Replace launch-setting to "remotePath": "gopath/src/hello", in vscode.

objdump trimpath hello:
here you can see path "gopath/src/hello/hello.go"

$  go tool objdump hello | grep hello.go
TEXT main.main(SB) gopath/src/hello/hello.go
  hello.go:8            0x48d160                64488b0c25f8ffffff      MOVQ FS:0xfffffff8, CX
...

Dlv log on linux server set breakpoint successful:

...
2019-12-06T13:40:49Z debug layer=rpc <- RPCServer.CreateBreakpoint(rpc2.CreateBreakpointIn{"Breakpoint":{"id":0,"name":"","addr":0,"file":"gopath/src/hello/hello.go","line":10,"Cond":"","continue":false,"traceReturn":false,"goroutine":fals
e,"stacktrace":0,"LoadArgs":{"FollowPointers":true,"MaxVariableRecurse":1,"MaxStringLen":64,"MaxArrayValues":64,"MaxStructFields":-1},"LoadLocals":{"FollowPointers":true,"MaxVariableRecurse":1,"MaxStringLen":64,"MaxArrayValues":64,"MaxStru
ctFields":-1},"hitCount":null,"totalHitCount":0}})                                                                                                                                                                                             
2019-12-06T13:40:49Z info layer=debugger created breakpoint: &api.Breakpoint{ID:1, Name:"", Addr:0x48d181, File:"gopath/src/hello/hello.go", Line:10, FunctionName:"main.main", Cond:"", Tracepoint:false, TraceReturn:false, Goroutine:false, 
Stacktrace:0, Variables:[]string(nil), LoadArgs:(*api.LoadConfig)(0xc000029290), LoadLocals:(*api.LoadConfig)(0xc0000292c0), HitCount:map[string]uint64{}, TotalHitCount:0x0}                                                                  
...
@ramya-rao-a
Copy link
Contributor

Thanks for reporting @deschmih

@quoctruong Can you take a look at this?

@quoctruong
Copy link
Contributor

@deschmih I think this is the correct behavior. You have to specify both the remotePath and cwd (local path). remotePath would be the path on the Linux server (for example: /bin/src/hello) and the cwd can be something like ${workspaceFolder}/src/hello

@ramya-rao-a
Copy link
Contributor

@quoctruong Should we then throw an error if cwd is not provided if remotePath is used in attach mode?

cc @jhendrixMSFT

@deschmih
Copy link
Author

@quoctruong & @ramya-rao-a
Thanks for your effort, but I think it is not really clear what I am doing. I build a go binary on windows for a remote linux host (crosscompilation). So the path embedded in the binary is actually a windows path seperated by forward slashes (/).
I have changed my launch.json as suggested:

  "remotePath": "/data/epu/hello",
  "cwd": "c:/gopath/src/hello",

This results in the following output:

...
2019-12-12T14:24:57Z debug layer=rpc <- RPCServer.CreateBreakpoint(rpc2.CreateBreakpointIn{"Breakpoint":{"id":0,"name":"","addr":0,"file":"/data/epu/hello/hello.go","line":13,"Cond":"","continue":false,"traceReturn":false,"goroutine":false,"stacktrace":0,"LoadArgs":{"FollowPointers":true,"MaxVariableRecurse":1,"MaxStringLen":64,"MaxArrayValues":64,"MaxStructFields":-1},"LoadLocals":{"FollowPointers":true,"MaxVariableRecurse":1,"MaxStringLen":64,"MaxArrayValues":64,"MaxStructFields":-1},"hitCount":null,"totalHitCount":0}})
2019-12-12T14:24:57Z debug layer=rpc -> *rpc2.CreateBreakpointOut{"Breakpoint":{"id":0,"name":"","addr":0,"file":"","line":0,"Cond":"","continue":false,"traceReturn":false,"goroutine":false,"stacktrace":0,"LoadArgs":null,"LoadLocals":null,"hitCount":null,"totalHitCount":0}} error: "could not find file /data/epu/hello/hello.go"
...

This is what i would expect, because the binary contains the following path c:/gopath/src/hello/hello.go with slashes! (remember: the binary is cross-compiled)
What I would expect to work is the following configuration:

  "remotePath": "c:/gopath/src/hello",
  "cwd": "c:/gopath/src/hello",

This results in the following output:

...
2019-12-12T14:30:56Z debug layer=rpc <- RPCServer.CreateBreakpoint(rpc2.CreateBreakpointIn{"Breakpoint":{"id":0,"name":"","addr":0,"file":"c:\\gopath\\src\\hello\\hello.go","line":13,"Cond":"","continue":false,"traceReturn":false,"goroutine":false,"stacktrace":0,"LoadArgs":{"FollowPointers":true,"MaxVariableRecurse":1,"MaxStringLen":64,"MaxArrayValues":64,"MaxStructFields":-1},"LoadLocals":{"FollowPointers":true,"MaxVariableRecurse":1,"MaxStringLen":64,"MaxArrayValues":64,"MaxStructFields":-1},"hitCount":null,"totalHitCount":0}})
2019-12-12T14:30:56Z debug layer=rpc -> *rpc2.CreateBreakpointOut{"Breakpoint":{"id":0,"name":"","addr":0,"file":"","line":0,"Cond":"","continue":false,"traceReturn":false,"goroutine":false,"stacktrace":0,"LoadArgs":null,"LoadLocals":null,"hitCount":null,"totalHitCount":0}} error: "could not find file c:\\gopath\\src\\hello\\hello.go"
...

As you can see from the output, the path is nearly correct. Only the path separator does not match.
What I need is a way to specify the actual path the binary contains (using forward slash as path seperator)
It seems as if the code matches a Windows drive path (e.g. C:) and assumes the remote path separator to be "\" when it actually needs to be "/".

@quoctruong
Copy link
Contributor

@deschmih I see. I think forward slash should actually work on Windows too so perhaps we don't have to change the path separator to backslash. @jhendrixMSFT, @ramya-rao-a Do you see any problems with this?

@ramya-rao-a
Copy link
Contributor

@deschmih I would recommend that you try using the Go extension from the source to figure out exactly where we are messing up the path separators

@deschmih
Copy link
Author

Sorry for the late response. I have debugged my problem and the following changes solved my problem.

https://github.com/microsoft/vscode-go/blob/0.12.0/src/debugAdapter/goDebug.ts#L286-L292 changed to:

function normalizePath(filePath: string) {
	if (process.platform === 'win32') {
		filePath = path.normalize(filePath);
		filePath = fixDriveCasingInWindows(filePath)
		filePath = filePath.split("\\").join("/")
		return filePath
	}
	return filePath;
}

https://github.com/microsoft/vscode-go/blob/0.12.0/src/debugAdapter/goDebug.ts#L696-L701 changed to:

protected findPathSeperator(path: string) {
	if (/^(\w:[\\/]|\\\\)/.test(path)) {
		return '/';
	}
	return path.includes('/') ? '/' : '\\';
}

I think these changes do not match all usecases of the project, so I have spent more time to make the changes more special for my "windows" usecase.

This is the easy one:
https://github.com/microsoft/vscode-go/blob/0.12.0/src/debugAdapter/goDebug.ts#L696-L701 changed to:

protected findPathSeperator(path: string) {
	if (/^(\w:[\\]|\\\\)/.test(path)) {
		return '\\';
	} 

	if (/^(\w:[/])/.test(path)) {
		return '/';
	}
	
	return path.includes('/') ? '/' : '\\';
}

https://github.com/microsoft/vscode-go/blob/0.12.0/src/debugAdapter/goDebug.ts#L286-L292
In this case I have no information about the used path seperator, but these lines are essential for building the string for delve and send the formated filename to delve server.
This results in VS code sending the path "c:\gopath\src\hello\hello.go" as argument to the call SetBreakpoint which does not match the path "c:/gopath/src/hello/hello.go" embedded in the cross-compiled Linux binary. In my opinion we need here a LauchRequestAgrument to force (only if present) the string conversion in Line286-L292 to a specific path sepereator like:

function normalizePath(filePath: string, forcePathSeperator?: string) {
	if (process.platform === 'win32') {
		filePath = path.normalize(filePath);
		filePath = fixDriveCasingInWindows(filePath)
		if(forcePathSeperator != null) {
			filePath = filePath.split("\\").join(forcePathSeperator)
		}
		return filePath
	}
	return filePath;
}

Other ideas are welcome.

@deschmih
Copy link
Author

deschmih commented Feb 7, 2020

After long time of no action on this issue I have uninstalled vscode. Goland from jetbrain works fine for my purpose.

https://www.jetbrains.com/go/

Thanks for your support.

@deschmih deschmih closed this as completed Feb 7, 2020
@vscodebot vscodebot bot locked and limited conversation to collaborators Mar 23, 2020
@ramya-rao-a
Copy link
Contributor

The past few releases have seen improvements in the parts that @deschmih has outlined above. If anyone is still having problems with debugging, please log a new issue at https://github.com/golang/vscode-go as we are moving!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants