Skip to content

Commit 8c02b2e

Browse files
committed
cmd/compile: fix duplicated dwarf parameters for some functions
Dwarf formal parameters appear more than once in the final dwarf symbols for some functions. I believe there is an error up the chain where the vars are created and some of them are pushed more than once to the list. I ended up implementing a simple dedup mechanism to get rid of the duplicates up the chain, but this should be investigated deeper in a follow up ticket in order to find the root cause. The testing routine `findSubprogramDIE` was updated to panic in case it received duplicated formal parameters since this bug probably existed for quite a while and it was never discovered since this function basically pushes into a map indexed by the var name. A test has been added to cover this case as reported in the original issue ticket. Fixed: #61357
1 parent 2eca0b1 commit 8c02b2e

File tree

2 files changed

+44
-0
lines changed

2 files changed

+44
-0
lines changed

src/cmd/internal/dwarf/dwarf.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1204,11 +1204,21 @@ func putPrunedScopes(ctxt Context, s *FnState, fnabbrev int) error {
12041204
}
12051205
scopes := make([]Scope, len(s.Scopes), len(s.Scopes))
12061206
pvars := inlinedVarTable(&s.InlCalls)
1207+
dedupvars := make(map[string]bool)
12071208
for k, s := range s.Scopes {
12081209
var pruned Scope = Scope{Parent: s.Parent, Ranges: s.Ranges}
12091210
for i := 0; i < len(s.Vars); i++ {
1211+
// FIXME: This map was added to deduplicate the list of variables.
1212+
// Somewhere up the dwarf generation chain variables are added to the scope
1213+
// more than once.
1214+
_, dup := dedupvars[s.Vars[i].Name]
1215+
if dup {
1216+
continue
1217+
}
1218+
12101219
_, found := pvars[s.Vars[i]]
12111220
if !found {
1221+
dedupvars[s.Vars[i].Name] = true
12121222
pruned.Vars = append(pruned.Vars, s.Vars[i])
12131223
}
12141224
}

src/cmd/link/internal/ld/dwarf_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1608,6 +1608,7 @@ func processParams(die *dwarf.Entry, ex *dwtest.Examiner) string {
16081608
// Walk the subprogram DIE's children looking for params.
16091609
pIdx := ex.IdxFromOffset(die.Offset)
16101610
childDies := ex.Children(pIdx)
1611+
entryName := die.Val(dwarf.AttrName)
16111612
idx := 0
16121613
for _, child := range childDies {
16131614
if child.Tag == dwarf.TagFormalParameter {
@@ -1626,6 +1627,9 @@ func processParams(die *dwarf.Entry, ex *dwtest.Examiner) string {
16261627
}
16271628
}
16281629
if name, ok := child.Val(dwarf.AttrName).(string); ok {
1630+
if _, ok := foundParams[name]; ok {
1631+
panic(fmt.Sprintf("Found duplicated child parameter %s while parsing dwarf entry %s", name, entryName))
1632+
}
16291633
foundParams[name] = fmt.Sprintf("%d:%d", idx, st)
16301634
idx++
16311635
}
@@ -2024,3 +2028,33 @@ func main() {
20242028
})
20252029
}
20262030
}
2031+
2032+
func TestIssue61357(t *testing.T) {
2033+
// This test asserts that parameters are not duplicated
2034+
// in the generated dwarf symbols.
2035+
testenv.MustHaveGoBuild(t)
2036+
2037+
mustHaveDWARF(t)
2038+
t.Parallel()
2039+
2040+
const prog = `
2041+
package main
2042+
2043+
import "fmt"
2044+
2045+
func main() {
2046+
fmt.Println("Hello")
2047+
}
2048+
`
2049+
_, ex := gobuildAndExamine(t, prog, NoOpt)
2050+
2051+
die := findSubprogramDIE(t, ex, "internal/poll.(*FD).Write")
2052+
2053+
found := processParams(die, ex)
2054+
2055+
expected := "[fd:0:1 p:1:1 ~r0:2:2 ~r1:3:2]"
2056+
if found != expected {
2057+
t.Errorf("param check failed, wanted:\n%s\ngot:\n%s\n",
2058+
expected, found)
2059+
}
2060+
}

0 commit comments

Comments
 (0)