Skip to content

Commit 0f6566c

Browse files
committed
proc: use DW_AT_trampoline to detect auto-generated code
Use the trampoline attribute to detect auto-generated code. This fixes a bug where stepping into a method of a generic type called through an interface will take the debugger into an auto-generated wrapper that does not have a dictionary and using next will step out of the wrapper. Fixes a bug reported on the #delve channel of the gophers slack server.
1 parent 70f21c9 commit 0f6566c

File tree

4 files changed

+55
-2
lines changed

4 files changed

+55
-2
lines changed

_fixtures/genericintoiface.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package main
2+
3+
import "fmt"
4+
5+
type Blah[T any] struct {
6+
x T
7+
}
8+
9+
func (b *Blah[T]) F(y T) {
10+
b.x = y
11+
}
12+
13+
type BlahInt interface {
14+
F(int)
15+
}
16+
17+
func callf(b BlahInt) {
18+
b.F(2)
19+
fmt.Println(b)
20+
}
21+
22+
func main() {
23+
b := &Blah[int]{10}
24+
callf(b)
25+
}

pkg/proc/proc_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,7 @@ const (
428428
contReverseStep
429429
contReverseStepout
430430
contContinueToBreakpoint
431+
contNothing
431432
)
432433

433434
type seqTest struct {
@@ -531,6 +532,8 @@ func testseq2Args(wd string, args []string, buildFlags protest.BuildFlags, t *te
531532
assertNoError(grp.Continue(), t, "Continue() returned an error")
532533
err := p.ClearBreakpoint(bp.Addr)
533534
assertNoError(err, t, "ClearBreakpoint() returned an error")
535+
case contNothing:
536+
// do nothing
534537
}
535538

536539
f, ln = currentLineNumber(p, t)
@@ -552,6 +555,10 @@ func testseq2Args(wd string, args []string, buildFlags protest.BuildFlags, t *te
552555
if !strings.HasSuffix(f, v[0]) || (ln != tgtln) {
553556
t.Fatalf("Program did not continue to correct next location, expected %s was %s:%d (%#x) (testcase %d)", pos, filepath.Base(f), ln, pc, i)
554557
}
558+
case func(*proc.Target):
559+
pos(p)
560+
default:
561+
panic(fmt.Errorf("unexpected type %T", pos))
555562
}
556563
}
557564

@@ -6260,3 +6267,24 @@ func TestWaitForAttach(t *testing.T) {
62606267

62616268
cmd.Wait()
62626269
}
6270+
6271+
func TestNextGenericMethodThroughInterface(t *testing.T) {
6272+
// Tests that autogenerated wrappers for generic methods called through an
6273+
// interface are skipped.
6274+
testseq2(t, "genericintoiface", "main.callf", []seqTest{
6275+
{contContinue, 17},
6276+
{contStep, 18},
6277+
{contStep, 9},
6278+
{contNext, 10},
6279+
{contNothing, func(p *proc.Target) {
6280+
yvar := evalVariable(p, t, "y")
6281+
yval, _ := constant.Int64Val(yvar.Value)
6282+
if yval != 2 {
6283+
t.Errorf("expected 2 got %#v", yvar.Value)
6284+
}
6285+
6286+
}},
6287+
{contNext, 11},
6288+
{contNext, 19},
6289+
})
6290+
}

pkg/proc/target_exec.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -990,7 +990,7 @@ func allowDuplicateBreakpoint(bp *Breakpoint, err error) (*Breakpoint, error) {
990990
}
991991

992992
func isAutogenerated(loc Location) bool {
993-
return loc.File == "<autogenerated>" && loc.Line == 1
993+
return (loc.File == "<autogenerated>" && loc.Line == 1) || (loc.Fn != nil && loc.Fn.trampoline)
994994
}
995995

996996
func isAutogeneratedOrDeferReturn(loc Location) bool {

pkg/proc/variables.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1191,7 +1191,7 @@ func extractVarInfoFromEntry(tgt *Target, bi *BinaryInfo, image *Image, regs op.
11911191
t, err = resolveParametricType(bi, mem, t, dictAddr)
11921192
if err != nil {
11931193
// Log the error, keep going with t, which will be the shape type
1194-
logflags.DebuggerLogger().Errorf("could not resolve parametric type of %s", n)
1194+
logflags.DebuggerLogger().Errorf("could not resolve parametric type of %s: %v", n, err)
11951195
}
11961196

11971197
addr, pieces, descr, err := bi.Location(entry, dwarf.AttrLocation, regs.PC(), regs, mem)

0 commit comments

Comments
 (0)