diff --git a/src/cmd/internal/dwarf/dwarf.go b/src/cmd/internal/dwarf/dwarf.go index d4a4e33652d01a..82b92e8888b749 100644 --- a/src/cmd/internal/dwarf/dwarf.go +++ b/src/cmd/internal/dwarf/dwarf.go @@ -1204,11 +1204,21 @@ func putPrunedScopes(ctxt Context, s *FnState, fnabbrev int) error { } scopes := make([]Scope, len(s.Scopes), len(s.Scopes)) pvars := inlinedVarTable(&s.InlCalls) + dedupvars := make(map[string]bool) for k, s := range s.Scopes { var pruned Scope = Scope{Parent: s.Parent, Ranges: s.Ranges} for i := 0; i < len(s.Vars); i++ { + // FIXME: This map was added to deduplicate the list of variables. + // When generating the formal parameters from the symbols some variables + // were added to the scope more than once. + _, dup := dedupvars[s.Vars[i].Name] + if dup { + continue + } + _, found := pvars[s.Vars[i]] if !found { + dedupvars[s.Vars[i].Name] = true pruned.Vars = append(pruned.Vars, s.Vars[i]) } } diff --git a/src/cmd/link/internal/ld/dwarf_test.go b/src/cmd/link/internal/ld/dwarf_test.go index 6ca2a844f5cffc..98e81f9175a140 100644 --- a/src/cmd/link/internal/ld/dwarf_test.go +++ b/src/cmd/link/internal/ld/dwarf_test.go @@ -1608,6 +1608,7 @@ func processParams(die *dwarf.Entry, ex *dwtest.Examiner) string { // Walk the subprogram DIE's children looking for params. pIdx := ex.IdxFromOffset(die.Offset) childDies := ex.Children(pIdx) + entryName := die.Val(dwarf.AttrName) idx := 0 for _, child := range childDies { if child.Tag == dwarf.TagFormalParameter { @@ -1626,6 +1627,9 @@ func processParams(die *dwarf.Entry, ex *dwtest.Examiner) string { } } if name, ok := child.Val(dwarf.AttrName).(string); ok { + if _, ok := foundParams[name]; ok { + panic(fmt.Sprintf("Found duplicated child parameter %s while parsing dwarf entry %s\n", name, entryName)) + } foundParams[name] = fmt.Sprintf("%d:%d", idx, st) idx++ } @@ -2024,3 +2028,33 @@ func main() { }) } } + +func TestIssue61357(t *testing.T) { + // This test asserts that parameters are not duplicated + // in the generated dwarf symbols. + testenv.MustHaveGoBuild(t) + + mustHaveDWARF(t) + t.Parallel() + + const prog = ` +package main + +import "fmt" + +func main() { + fmt.Println("Hello") +} +` + _, ex := gobuildAndExamine(t, prog, NoOpt) + + die := findSubprogramDIE(t, ex, "internal/poll.(*FD).Write") + + found := processParams(die, ex) + + expected := "[fd:0:1 p:1:1 ~r0:2:2 ~r1:3:2]" + if found != expected { + t.Errorf("param check failed, wanted:\n%s\ngot:\n%s\n", + expected, found) + } +}