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

What should we do if a linespec does not resolve to any instruction #840

Closed
dlsniper opened this issue May 14, 2017 · 10 comments
Closed

What should we do if a linespec does not resolve to any instruction #840

dlsniper opened this issue May 14, 2017 · 10 comments

Comments

@dlsniper
Copy link
Contributor

  1. What version of Delve are you using (dlv version)?
    derekparker/delve@82d142d
  2. What version of Go are you using? (go version)?
    go 1.8.1
  3. What operating system and processor architecture are you using?
    Windows 10 / amd64
  4. What did you do?
    demo.go
package main

type TableModel struct {}

func (TableModel) TableName() string {
	return ""
}

func demo(a interface{}) (v1 string, v2 bool) {
	if tm, ok := a.(TableModel); ok {
		return tm.TableName(), ok
	}
	return "", false
}

func main() {
	a := TableModel{} // b demo.go:17
	demo(a)
}
go build -gcflags "-N -l" -o tmp.exe demo.go
dlv.exe --backend=default exec ./tmp.exe
  1. What did you expect to see?
    I would expect to have a breakpoint on that line and the debugger to stop on it.
  2. What did you see instead?
Command failed: no code at demo.go:17
@aarzilli
Copy link
Member

These are the instructions produced for that main function:

TEXT main.main(SB) /home/a/temp/demo.go
        demo.go:16      0x44d6c0        64488b0c25f8ffffff      FS MOVQ FS:0xfffffff8, CX               
        demo.go:16      0x44d6c9        483b6110                CMPQ 0x10(CX), SP                       
        demo.go:16      0x44d6cd        7632                    JBE 0x44d701                            
        demo.go:16      0x44d6cf        4883ec30                SUBQ $0x30, SP                          
        demo.go:16      0x44d6d3        48896c2428              MOVQ BP, 0x28(SP)                       
        demo.go:16      0x44d6d8        488d6c2428              LEAQ 0x28(SP), BP                       
        demo.go:18      0x44d6dd        488d05bced0000          LEAQ 0xedbc(IP), AX                     
        demo.go:18      0x44d6e4        48890424                MOVQ AX, 0(SP)                          
        demo.go:18      0x44d6e8        488d442428              LEAQ 0x28(SP), AX                       
        demo.go:18      0x44d6ed        4889442408              MOVQ AX, 0x8(SP)                        
        demo.go:18      0x44d6f2        e8e9feffff              CALL main.demo(SB)                      
        demo.go:19      0x44d6f7        488b6c2428              MOVQ 0x28(SP), BP                       
        demo.go:19      0x44d6fc        4883c430                ADDQ $0x30, SP                          
        demo.go:19      0x44d700        c3                      RET                                     
        demo.go:16      0x44d701        e8ea84ffff              CALL runtime.morestack_noctxt(SB)       
        demo.go:16      0x44d706        ebb8                    JMP main.main(SB)                       

Nothing is produced for line 17, the reason this happens is that TableModel is a zero sized struct and no work is required to initialize it. It doesn't have anything to do with :=. Gdb puts a breakpoint on the first line containing code at or after the line specified, we could do that somewhere. Otherwise there's nothing to do here, I don't think this even counts as a upstream bug.

@aarzilli aarzilli changed the title Breakpoint doesn't stop in shorthand assignment What should we do if a linespec does not resolve to any instruction May 15, 2017
@dlsniper
Copy link
Contributor Author

Hmm, I understand this but I'd rather see as an upstream problem.
It took me a bit of time to understand what's happening and I've had assistance from @dominikh and @ScottMansfield for this, not sure how many people will be this lucky.
The issue is about expectations. If I set a breakpoint on a line, I expect the debugger to stop there, especially when I'm aware what optimizations are turned of for the compiled target.
I think this maybe should be discussed with the Go team and see what they think about it?

As for maybe stopping the debugger on the following line it would be a good thing? I got surprised the first time the debugger didn't stopped at all and this is part of a bigger code, reproduced in smaller scale for example sake.

Thank you for your time and help.

@aarzilli
Copy link
Member

aarzilli commented May 16, 2017

The issue is about expectations. If I set a breakpoint on a line, I expect the debugger to stop there

Of course. OTOH if you try to set a breakpoint on an empty line, a comment or a close brace you would expect the debugger to complain (or maybe to set the breakpoint on the next available line?).
This case is a lot less obvious, but it's also an fairly rare edge case and the only way to have a debugger stop on that line would be for the compiler to remember to emit a NOP for that line.

@dlsniper
Copy link
Contributor Author

This case is a lot less obvious, but it's also an fairly rare edge case and the only way to have a debugger stop on that line would be for the compiler to remember to emit a NOP for that line.

As far as I can tell, running go build -gcflags="-S -N -l" demo.go will generate the NOP for that line and we already know that for debugging you should build with something like this: go build -gcflags="-N -l" demo.go. As far as I understand how this works is that -S doesn't (or shouldn't) have any effect over the final generated assembly whereas -N -l should (as they do already).

"".main t=1 size=72 args=0x0 locals=0x30
        0x0000 00000 (/home/florin/go/src/github.com/dlsniper/u/tmp/demo.go:16) TEXT    "".main(SB), $48-0
        0x0000 00000 (/home/florin/go/src/github.com/dlsniper/u/tmp/demo.go:16) MOVQ    (TLS), CX
        0x0009 00009 (/home/florin/go/src/github.com/dlsniper/u/tmp/demo.go:16) CMPQ    SP, 16(CX)
        0x000d 00013 (/home/florin/go/src/github.com/dlsniper/u/tmp/demo.go:16) JLS     65
        0x000f 00015 (/home/florin/go/src/github.com/dlsniper/u/tmp/demo.go:16) SUBQ    $48, SP
        0x0013 00019 (/home/florin/go/src/github.com/dlsniper/u/tmp/demo.go:16) MOVQ    BP, 40(SP)
        0x0018 00024 (/home/florin/go/src/github.com/dlsniper/u/tmp/demo.go:16) LEAQ    40(SP), BP
        0x001d 00029 (/home/florin/go/src/github.com/dlsniper/u/tmp/demo.go:16) FUNCDATA        $0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
        0x001d 00029 (/home/florin/go/src/github.com/dlsniper/u/tmp/demo.go:16) FUNCDATA        $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
        0x001d 00029 (/home/florin/go/src/github.com/dlsniper/u/tmp/demo.go:17) NOP
        0x001d 00029 (/home/florin/go/src/github.com/dlsniper/u/tmp/demo.go:18) NOP
        0x001d 00029 (/home/florin/go/src/github.com/dlsniper/u/tmp/demo.go:18) LEAQ    type."".TableModel(SB), AX
        0x0024 00036 (/home/florin/go/src/github.com/dlsniper/u/tmp/demo.go:18) MOVQ    AX, (SP)
        0x0028 00040 (/home/florin/go/src/github.com/dlsniper/u/tmp/demo.go:18) LEAQ    ""..autotmp_3+40(SP), AX
        0x002d 00045 (/home/florin/go/src/github.com/dlsniper/u/tmp/demo.go:18) MOVQ    AX, 8(SP)
        0x0032 00050 (/home/florin/go/src/github.com/dlsniper/u/tmp/demo.go:18) PCDATA  $0, $0
        0x0032 00050 (/home/florin/go/src/github.com/dlsniper/u/tmp/demo.go:18) CALL    "".demo(SB)
        0x0037 00055 (/home/florin/go/src/github.com/dlsniper/u/tmp/demo.go:18) NOP
        0x0037 00055 (/home/florin/go/src/github.com/dlsniper/u/tmp/demo.go:19) MOVQ    40(SP), BP
        0x003c 00060 (/home/florin/go/src/github.com/dlsniper/u/tmp/demo.go:19) ADDQ    $48, SP
        0x0040 00064 (/home/florin/go/src/github.com/dlsniper/u/tmp/demo.go:19) RET
        0x0041 00065 (/home/florin/go/src/github.com/dlsniper/u/tmp/demo.go:19) NOP
        0x0041 00065 (/home/florin/go/src/github.com/dlsniper/u/tmp/demo.go:16) PCDATA  $0, $-1
        0x0041 00065 (/home/florin/go/src/github.com/dlsniper/u/tmp/demo.go:16) CALL    runtime.morestack_noctxt(SB)
        0x0046 00070 (/home/florin/go/src/github.com/dlsniper/u/tmp/demo.go:16) JMP     0

Thank you.

@aarzilli
Copy link
Member

Judging by the PCDATA/FUNCDATA stuff, I think that's actually printing go's intermediate representation rather than assembly. I imagine NOPs get compiled into nothing. BTW tip doesn't emit them in the intermediate representation either.

@justinclift
Copy link
Contributor

That being the case, what would it take for getting the NOP to be compiled in? This use case is probably important enough that a switch could be added for it. 😉

Hmmm, is this something which should be opened upstream instead? 😄

@dlsniper
Copy link
Contributor Author

I've opened up golang/go#20487 as a follow-up. Regarding the suggestion to stop on the next closest line, I guess that could work meanwhile, even if the users will be a bit more confused?

@au-phiware
Copy link

Regarding the suggestion to stop on the next closest line, I guess that could work meanwhile, even if the users will be a bit more confused?

If the user is trying to set a breakpoint on a line that contains only a comment (or whatever) then they are already confused... if it was me I'd want a breakpoint set. Is it better to set a breakpoint and emit a warning or only emit an error. (It seems to me a lot of folks don't read the normal messages, and so would easily miss any error or warning, unless it be colourised!)

@justinclift
Copy link
Contributor

justinclift commented Aug 15, 2017

Hmmm, there's also the situation where the user deletes a few lines of existing code with a breakpoint in it somewhere. Some IDE's might still leave the breakpoint at the same line number, which could be non-code after the delete.

Whether or not that's good behaviour on the IDE's part I guess would depend on the IDE's general way of doing things. 😄

@aarzilli
Copy link
Member

We didn't change anything and this issue hasn't really received any attention in the past 7 years. Our current behavior is probably fine.

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

No branches or pull requests

4 participants