aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThan McIntosh <thanm@google.com>2017-12-06 20:10:51 -0500
committerThan McIntosh <thanm@google.com>2017-12-07 17:03:05 +0000
commit692f2e9c44e629e84b315f10c8538c9461fd6d61 (patch)
treea2bef2c228a6cfa80d0d710b1e2fcc37b294a0e6
parent8b13988e40e468995360802a2dc7de9b32a34fea (diff)
downloadgo-692f2e9c44e629e84b315f10c8538c9461fd6d61.tar.gz
go-692f2e9c44e629e84b315f10c8538c9461fd6d61.zip
cmd/compile: fix bug in logic for computing var abstract origins
The DWARF inline info generation code was using file/line/column (from src.Pos) as a means of matching up pre- and post-optimization variable nodes. This turns out to be problematic since it looks as though distinct formals on the same line can be assigned the same column number. Work around this issue by adding variable names to the disambiguation code. Added a testpoint to the linker DWARF test that checks to make sure each abstract origin offset of distinct within a given DWARF DW_AT_inlined_routine body. Fixes #23020. Change-Id: Ie09bbe01dc60822d84d4085547b138e644036fb3 Reviewed-on: https://go-review.googlesource.com/82396 Reviewed-by: David Chase <drchase@google.com> Reviewed-by: Cherry Zhang <cherryyz@google.com>
-rw-r--r--src/cmd/compile/internal/gc/dwinl.go6
-rw-r--r--src/cmd/link/internal/ld/dwarf_test.go25
2 files changed, 30 insertions, 1 deletions
diff --git a/src/cmd/compile/internal/gc/dwinl.go b/src/cmd/compile/internal/gc/dwinl.go
index f76bacc5b9..dd91b6c0fc 100644
--- a/src/cmd/compile/internal/gc/dwinl.go
+++ b/src/cmd/compile/internal/gc/dwinl.go
@@ -14,6 +14,7 @@ import (
// To identify variables by original source position.
type varPos struct {
+ DeclName string
DeclFile string
DeclLine uint
DeclCol uint
@@ -96,14 +97,19 @@ func assembleInlines(fnsym *obj.LSym, fn *Node, dwVars []*dwarf.Var) dwarf.InlCa
n := dcl[i]
pos := Ctxt.InnermostPos(n.Pos)
vp := varPos{
+ DeclName: n.Sym.Name,
DeclFile: pos.Base().SymFilename(),
DeclLine: pos.Line(),
DeclCol: pos.Col(),
}
+ if _, found := m[vp]; found {
+ Fatalf("child dcl collision on symbol %s within %v\n", n.Sym.Name, fnsym.Name)
+ }
m[vp] = i
}
for j := 0; j < len(sl); j++ {
vp := varPos{
+ DeclName: sl[j].Name,
DeclFile: sl[j].DeclFile,
DeclLine: sl[j].DeclLine,
DeclCol: sl[j].DeclCol,
diff --git a/src/cmd/link/internal/ld/dwarf_test.go b/src/cmd/link/internal/ld/dwarf_test.go
index 0bd5133f48..4332a3dfba 100644
--- a/src/cmd/link/internal/ld/dwarf_test.go
+++ b/src/cmd/link/internal/ld/dwarf_test.go
@@ -522,8 +522,13 @@ package main
var G int
+func noinline(x int) int {
+ defer func() { G += x }()
+ return x
+}
+
func cand(x, y int) int {
- return (x + y) ^ (y - x)
+ return noinline(x+y) ^ (y - x)
}
func main() {
@@ -599,6 +604,24 @@ func main() {
}
}
exCount++
+
+ omap := make(map[dwarf.Offset]bool)
+
+ // Walk the child variables of the inlined routine. Each
+ // of them should have a distinct abstract origin-- if two
+ // vars point to the same origin things are definitely broken.
+ inlIdx := ex.idxFromOffset(child.Offset)
+ inlChildDies := ex.Children(inlIdx)
+ for _, k := range inlChildDies {
+ ooff, originOK := k.Val(dwarf.AttrAbstractOrigin).(dwarf.Offset)
+ if !originOK {
+ t.Fatalf("no abstract origin attr for child of inlined subroutine at offset %v", k.Offset)
+ }
+ if _, found := omap[ooff]; found {
+ t.Fatalf("duplicate abstract origin at child of inlined subroutine at offset %v", k.Offset)
+ }
+ omap[ooff] = true
+ }
}
}
if exCount != len(expectedInl) {