import (
"cmd/compile/internal/types"
- "cmd/internal/src"
"fmt"
)
lineno = autogeneratedPos // less confusing than end of input
dclcontext = PEXTERN
- markdcl(src.NoPos)
+ markdcl()
// func sym(p *T, h uintptr) uintptr
fn := nod(ODCLFUNC, nil, nil)
n = anonfield(types.Types[TUINTPTR]) // return value
tfn.Rlist.Append(n)
- funchdr(fn, src.NoPos)
+ funchdr(fn)
fn.Func.Nname.Name.Param.Ntype = typecheck(fn.Func.Nname.Name.Param.Ntype, Etype)
// genhash is only called for types that have equality but
dumplist("genhash body", fn.Nbody)
}
- funcbody(fn, src.NoPos)
+ funcbody(fn)
Curfn = fn
fn.Func.SetDupok(true)
fn = typecheck(fn, Etop)
typecheckslice(fn.Nbody.Slice(), Etop)
- popdcl(src.NoPos)
Curfn = nil
+ popdcl()
if debug_dclstack != 0 {
testdclstack()
}
lineno = autogeneratedPos // less confusing than end of input
dclcontext = PEXTERN
- markdcl(src.NoPos)
+ markdcl()
// func sym(p, q *T) bool
fn := nod(ODCLFUNC, nil, nil)
n = anonfield(types.Types[TBOOL])
tfn.Rlist.Append(n)
- funchdr(fn, src.NoPos)
+ funchdr(fn)
fn.Func.Nname.Name.Param.Ntype = typecheck(fn.Func.Nname.Name.Param.Ntype, Etype)
// geneq is only called for types that have equality but
dumplist("geneq body", fn.Nbody)
}
- funcbody(fn, src.NoPos)
+ funcbody(fn)
Curfn = fn
fn.Func.SetDupok(true)
fn = typecheck(fn, Etop)
typecheckslice(fn.Nbody.Slice(), Etop)
- popdcl(src.NoPos)
Curfn = nil
+ popdcl()
if debug_dclstack != 0 {
testdclstack()
}
if f := p.funcList[i]; f != nil {
// function not yet imported - read body and set it
- funchdr(f, src.NoPos)
+ funchdr(f)
body := p.stmtList()
if body == nil {
// Make sure empty body is not interpreted as
body = []*Node{nod(OEMPTY, nil, nil)}
}
f.Func.Inl.Set(body)
- funcbody(f, src.NoPos)
+ funcbody(f)
} else {
// function already imported - read body but discard declarations
dclcontext = PDISCARD // throw away any declarations
return nodl(p.pos(), op, p.expr(), nil)
case OIF:
- markdcl(src.NoPos)
+ markdcl()
n := nodl(p.pos(), OIF, nil, nil)
n.Ninit.Set(p.stmtList())
n.Left = p.expr()
n.Nbody.Set(p.stmtList())
n.Rlist.Set(p.stmtList())
- popdcl(src.NoPos)
+ popdcl()
return n
case OFOR:
- markdcl(src.NoPos)
+ markdcl()
n := nodl(p.pos(), OFOR, nil, nil)
n.Ninit.Set(p.stmtList())
n.Left, n.Right = p.exprsOrNil()
n.Nbody.Set(p.stmtList())
- popdcl(src.NoPos)
+ popdcl()
return n
case ORANGE:
- markdcl(src.NoPos)
+ markdcl()
n := nodl(p.pos(), ORANGE, nil, nil)
n.List.Set(p.stmtList())
n.Right = p.expr()
n.Nbody.Set(p.stmtList())
- popdcl(src.NoPos)
+ popdcl()
return n
case OSELECT, OSWITCH:
- markdcl(src.NoPos)
+ markdcl()
n := nodl(p.pos(), op, nil, nil)
n.Ninit.Set(p.stmtList())
n.Left, _ = p.exprsOrNil()
n.List.Set(p.stmtList())
- popdcl(src.NoPos)
+ popdcl()
return n
// case OCASE, OXCASE:
// unreachable - mapped to OXCASE case below by exporter
case OXCASE:
- markdcl(src.NoPos)
+ markdcl()
n := nodl(p.pos(), OXCASE, nil, nil)
n.Xoffset = int64(block)
n.List.Set(p.exprList())
// TODO(gri) eventually we must declare variables for type switch
// statements (type switch statements are not yet exported)
n.Nbody.Set(p.stmtList())
- popdcl(src.NoPos)
+ popdcl()
return n
// case OFALL:
import (
"cmd/compile/internal/types"
- "cmd/internal/src"
"fmt"
)
n.Func.Depth = funcdepth
n.Func.Outerfunc = Curfn
- funchdr(n, src.NoPos)
+ funchdr(n)
// steal ntype's argument names and
// leave a fresh copy in their place.
func_ := Curfn
func_.Nbody.Set(body)
func_.Func.Endlineno = lineno
- funcbody(func_, src.NoPos)
+ funcbody(func_)
// closure-specific variables are hanging off the
// ordinary ones in the symbol table; see oldname.
}
xfunc.Nbody.Set(func_.Nbody.Slice())
- xfunc.Func.scopes = func_.Func.scopes
xfunc.Func.Dcl = append(func_.Func.Dcl, xfunc.Func.Dcl...)
func_.Func.Dcl = nil
- func_.Func.scopes.Scopes = nil
if xfunc.Nbody.Len() == 0 {
Fatalf("empty body - won't generate any code")
}
xfunc.Func.Nname.Sym.SetExported(true) // disable export
xfunc.Func.Nname.Name.Param.Ntype = xtype
xfunc.Func.Nname.Name.Defn = xfunc
- xfunc.Func.scopes.Scopes = []src.Scope{src.Scope{}}
declare(xfunc.Func.Nname, PFUNC)
// Declare and initialize variable holding receiver.
// Sym definitions, and only a subset of its fields are actually used.
var dclstack *types.Sym
-// lastPopdclPos is the last pos passed to popdcl
-var lastPopdclPos src.Pos
-
func dcopy(a, b *types.Sym) {
a.Pkg = b.Pkg
a.Name = b.Name
// popdcl pops the innermost block scope and restores all symbol declarations
// to their previous state.
-func popdcl(pos src.Pos) {
+func popdcl() {
d := dclstack
for ; d != nil && d.Name != ""; d = d.Link {
s := d.Pkg.Lookup(d.Name)
dclstack = d.Link // pop mark
block = d.Block
-
- if Curfn != nil {
- Curfn.Func.scopes.Close(&Ctxt.PosTable, pos)
- lastPopdclPos = pos
- }
-
- return
}
// markdcl records the start of a new block scope for declarations.
-func markdcl(pos src.Pos) {
+func markdcl() {
d := push()
d.Name = "" // used as a mark in fifo
d.Block = block
blockgen++
block = blockgen
-
- if Curfn != nil {
- Curfn.Func.scopes.Open(&Ctxt.PosTable, pos)
- }
-
- return
}
// keep around for debugging
// and declare the arguments.
// called in extern-declaration context
// returns in auto-declaration context.
-func funchdr(n *Node, pos src.Pos) {
+func funchdr(n *Node) {
// change the declaration context from extern to auto
if funcdepth == 0 && dclcontext != PEXTERN {
Fatalf("funchdr: dclcontext = %d", dclcontext)
}
dclcontext = PAUTO
- funcstart(n, pos)
+ funcstart(n)
if n.Func.Nname != nil {
funcargs(n.Func.Nname.Name.Param.Ntype)
// start the function.
// called before funcargs; undone at end of funcbody.
-func funcstart(n *Node, pos src.Pos) {
+func funcstart(n *Node) {
+ markdcl()
funcstack = append(funcstack, Curfn)
funcdepth++
Curfn = n
- markdcl(pos)
}
// finish the body.
// called in auto-declaration context.
// returns in extern-declaration context.
-func funcbody(n *Node, pos src.Pos) {
+func funcbody(n *Node) {
// change the declaration context from auto to extern
if dclcontext != PAUTO {
Fatalf("funcbody: unexpected dclcontext %d", dclcontext)
}
- popdcl(pos)
+ popdcl()
funcstack, Curfn = funcstack[:len(funcstack)-1], funcstack[len(funcstack)-1]
funcdepth--
if funcdepth == 0 {
package gc
-import (
- "cmd/compile/internal/types"
- "cmd/internal/src"
-)
+import "cmd/compile/internal/types"
// a function named init is a special case.
// it is called by the initialization before
fn.Func.Nname.Name.Defn = fn
fn.Func.Nname.Name.Param.Ntype = nod(OTFUNC, nil, nil)
declare(fn.Func.Nname, PFUNC)
- funchdr(fn, src.NoPos)
+ funchdr(fn)
// (3)
a := nod(OIF, nil, nil)
exportsym(fn.Func.Nname)
fn.Nbody.Set(r)
- funcbody(fn, src.NoPos)
+ funcbody(fn)
Curfn = fn
fn = typecheck(fn, Etop)
declare(f.Func.Nname, PFUNC)
}
- funchdr(f, fun.Pos())
+ funchdr(f)
if fun.Body != nil {
if f.Noescape() {
}
}
- funcbody(f, fun.Pos())
+ funcbody(f)
return f
}
}
func (p *noder) blockStmt(stmt *syntax.BlockStmt) []*Node {
- markdcl(stmt.Pos())
+ markdcl()
nodes := p.stmts(stmt.List)
- popdcl(stmt.Rbrace)
+ popdcl()
return nodes
}
func (p *noder) ifStmt(stmt *syntax.IfStmt) *Node {
- markdcl(stmt.Pos())
+ markdcl()
n := p.nod(stmt, OIF, nil, nil)
if stmt.Init != nil {
n.Ninit.Set1(p.stmt(stmt.Init))
n.Rlist.Set1(e)
}
}
- popdcl(lastPopdclPos)
+ popdcl()
return n
}
func (p *noder) forStmt(stmt *syntax.ForStmt) *Node {
- markdcl(stmt.Pos())
+ markdcl()
var n *Node
if r, ok := stmt.Init.(*syntax.RangeClause); ok {
if stmt.Cond != nil || stmt.Post != nil {
}
}
n.Nbody.Set(p.blockStmt(stmt.Body))
- popdcl(stmt.Body.Rbrace)
+ popdcl()
return n
}
func (p *noder) switchStmt(stmt *syntax.SwitchStmt) *Node {
- markdcl(stmt.Pos())
+ markdcl()
n := p.nod(stmt, OSWITCH, nil, nil)
if stmt.Init != nil {
n.Ninit.Set1(p.stmt(stmt.Init))
tswitch = nil
}
- n.List.Set(p.caseClauses(stmt.Body, tswitch, stmt.Rbrace))
+ n.List.Set(p.caseClauses(stmt.Body, tswitch))
- popdcl(stmt.Rbrace)
+ popdcl()
return n
}
-func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *Node, rbrace src.Pos) []*Node {
+func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *Node) []*Node {
var nodes []*Node
- for i, clause := range clauses {
+ for _, clause := range clauses {
p.lineno(clause)
- markdcl(clause.Pos())
+ markdcl()
n := p.nod(clause, OXCASE, nil, nil)
if clause.Cases != nil {
n.List.Set(p.exprList(clause.Cases))
}
n.Xoffset = int64(block)
n.Nbody.Set(p.stmts(clause.Body))
- if i+1 < len(clauses) {
- popdcl(clauses[i+1].Pos())
- } else {
- popdcl(rbrace)
- }
+ popdcl()
nodes = append(nodes, n)
}
return nodes
func (p *noder) selectStmt(stmt *syntax.SelectStmt) *Node {
n := p.nod(stmt, OSELECT, nil, nil)
- n.List.Set(p.commClauses(stmt.Body, stmt.Rbrace))
+ n.List.Set(p.commClauses(stmt.Body))
return n
}
-func (p *noder) commClauses(clauses []*syntax.CommClause, rbrace src.Pos) []*Node {
+func (p *noder) commClauses(clauses []*syntax.CommClause) []*Node {
var nodes []*Node
- for i, clause := range clauses {
+ for _, clause := range clauses {
p.lineno(clause)
- markdcl(clause.Pos())
+ markdcl()
n := p.nod(clause, OXCASE, nil, nil)
if clause.Comm != nil {
n.List.Set1(p.stmt(clause.Comm))
}
n.Xoffset = int64(block)
n.Nbody.Set(p.stmts(clause.Body))
- if i+1 < len(clauses) {
- popdcl(clauses[i+1].Pos())
- } else {
- popdcl(rbrace)
- }
+ popdcl()
nodes = append(nodes, n)
}
return nodes
pp.Free()
}
-func debuginfo(fnsym *obj.LSym, curfn interface{}) []dwarf.Scope {
+func debuginfo(fnsym *obj.LSym, curfn interface{}) []*dwarf.Var {
fn := curfn.(*Node)
if expect := Linksym(fn.Func.Nname.Sym); fnsym != expect {
Fatalf("unexpected fnsym: %v != %v", fnsym, expect)
}
- scopes := make([]dwarf.Scope, len(fn.Func.scopes.Scopes))
-
- for i := range scopes {
- scopes[i] = dwarf.Scope{Scope: fn.Func.scopes.Scopes[i]}
- }
-
+ var vars []*dwarf.Var
for _, n := range fn.Func.Dcl {
if n.Op != ONAME { // might be OTYPE or OLITERAL
continue
continue
}
- var scope int32 = 0
- // Only record scope information when inlining is disabled.
- if Debug['l'] == 0 {
- scope = findScope(n.Pos, scopes)
- }
-
typename := dwarf.InfoPrefix + gotype.Name[len("type."):]
- scopes[scope].Vars = append(scopes[scope].Vars, &dwarf.Var{
+ vars = append(vars, &dwarf.Var{
Name: n.Sym.Name,
Abbrev: abbrev,
Offset: int32(offs),
}
// Stable sort so that ties are broken with declaration order.
- for i := range scopes {
- sort.Stable(dwarf.VarsByOffset(scopes[i].Vars))
- }
-
- scopeRanges(fnsym, scopes)
+ sort.Stable(dwarf.VarsByOffset(vars))
- return scopes
+ return vars
}
// fieldtrack adds R_USEFIELD relocations to fnsym to record any
+++ /dev/null
-// Copyright 2017 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package gc
-
-import (
- "cmd/internal/dwarf"
- "cmd/internal/obj"
- "cmd/internal/src"
-)
-
-// findScope returns the most specific scope containing pos.
-func findScope(pos src.XPos, scopes []dwarf.Scope) int32 {
- if !pos.IsKnown() {
- return 0
- }
- for i := len(scopes) - 1; i > 0; i-- {
- if pos.After(scopes[i].Start) && pos.Before(scopes[i].End) {
- return int32(i)
- }
- }
- return 0
-}
-
-type scopedProg struct {
- p *obj.Prog
- scope int32
-}
-
-// scopeRanges calculates scope ranges for symbol fnsym.
-func scopeRanges(fnsym *obj.LSym, scopes []dwarf.Scope) {
- var sp []scopedProg
-
- for p := fnsym.Text; p != nil; p = p.Link {
- sp = append(sp, scopedProg{p, -1})
- }
-
- for scopeID := int32(len(scopes) - 1); scopeID >= 0; scopeID-- {
- if scope := &scopes[scopeID]; scope.Start.IsKnown() && scope.End.IsKnown() {
- scopeProgs(sp, scopeID, scope.Start, scope.End)
- }
- }
-
- scopedProgsToRanges(sp, scopes, fnsym.Size)
-
- // Propagate scope's pc ranges to parent
- for i := len(scopes) - 1; i > 0; i-- {
- cur := &scopes[i]
- if scopes[i].Parent != 0 {
- parent := &scopes[scopes[i].Parent]
- parent.UnifyRanges(cur)
- }
- }
-}
-
-// scopeProgs marks all scopedProgs between start and end that don't already
-// belong to a scope as belonging to scopeId.
-func scopeProgs(sp []scopedProg, scopeId int32, start, end src.XPos) {
- for i := range sp {
- if sp[i].scope >= 0 {
- continue
- }
- if pos := sp[i].p.Pos; pos.After(start) && pos.Before(end) {
- sp[i].scope = scopeId
- }
- }
-}
-
-// scopedProgsToRanges scans sp and collects in the Ranges field of each
-// scope the start and end instruction of the scope.
-func scopedProgsToRanges(sp []scopedProg, scopes []dwarf.Scope, symSize int64) {
- var curscope int32 = -1
- for i := range sp {
- if sp[i].scope == curscope {
- continue
- }
- if curscope >= 0 {
- curranges := scopes[curscope].Ranges
- curranges[len(curranges)-1].End = sp[i].p.Pc
- }
- curscope = sp[i].scope
- if curscope >= 0 {
- scopes[curscope].Ranges = append(scopes[curscope].Ranges, dwarf.Range{Start: sp[i].p.Pc, End: -1})
- }
- }
- if curscope >= 0 {
- curranges := scopes[curscope].Ranges
- curranges[len(curranges)-1].End = symSize
- }
-}
+++ /dev/null
-// Copyright 2016 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package gc_test
-
-import (
- "cmd/internal/objfile"
- "debug/dwarf"
- "internal/testenv"
- "io/ioutil"
- "os"
- "os/exec"
- "path/filepath"
- "sort"
- "strconv"
- "strings"
- "testing"
-)
-
-type testline struct {
- // line is one line of go source
- line string
-
- // scopes is a list of scope IDs of all the lexical scopes that this line
- // of code belongs to.
- // Scope IDs are assigned by traversing the tree of lexical blocks of a
- // function in pre-order
- // Scope IDs are function specific, i.e. scope 0 is always the root scope
- // of the function that this line belongs to. Empty scopes are not assigned
- // an ID (because they are not saved in debug_info).
- // Scope 0 is always omitted from this list since all lines always belong
- // to it.
- scopes []int
-
- // vars is the list of variables that belong in scopes[len(scopes)-1].
- // Local variables are prefixed with "var ", formal parameters with "arg ".
- // Must be ordered alphabetically.
- // Set to nil to skip the check.
- vars []string
-}
-
-var testfile = []testline{
- {line: "package main"},
- {line: "func f1(x int) { }"},
- {line: "func f2(x int) { }"},
- {line: "func f3(x int) { }"},
- {line: "func f4(x int) { }"},
- {line: "func f5(x int) { }"},
- {line: "func f6(x int) { }"},
- {line: "func gret1() int { return 2 }"},
- {line: "func gretbool() bool { return true }"},
- {line: "func gret3() (int, int, int) { return 0, 1, 2 }"},
- {line: "var v = []int{ 0, 1, 2 }"},
- {line: "var ch = make(chan int)"},
- {line: "var floatch = make(chan float64)"},
- {line: "var iface interface{}"},
- {line: "func TestNestedFor() {", vars: []string{"var a int"}},
- {line: " a := 0"},
- {line: " f1(a)"},
- {line: " for i := 0; i < 5; i++ {", scopes: []int{1}, vars: []string{"var i int"}},
- {line: " f2(i)", scopes: []int{1}},
- {line: " for i := 0; i < 5; i++ {", scopes: []int{1, 2}, vars: []string{"var i int"}},
- {line: " f3(i)", scopes: []int{1, 2}},
- {line: " }"},
- {line: " f4(i)", scopes: []int{1}},
- {line: " }"},
- {line: " f5(a)"},
- {line: "}"},
- {line: "func TestOas2() {", vars: []string{}},
- {line: " if a, b, c := gret3(); a != 1 {", scopes: []int{1}, vars: []string{"var a int", "var b int", "var c int"}},
- {line: " f1(a)", scopes: []int{1}},
- {line: " f1(b)", scopes: []int{1}},
- {line: " f1(c)", scopes: []int{1}},
- {line: " }"},
- {line: " for i, x := range v {", scopes: []int{2}, vars: []string{"var i int", "var x int"}},
- {line: " f1(i)", scopes: []int{2}},
- {line: " f1(x)", scopes: []int{2}},
- {line: " }"},
- {line: " if a, ok := <- ch; ok {", scopes: []int{3}, vars: []string{"var a int", "var ok bool"}},
- {line: " f1(a)", scopes: []int{3}},
- {line: " }"},
- {line: " if a, ok := iface.(int); ok {", scopes: []int{4}, vars: []string{"var a int", "var ok bool"}},
- {line: " f1(a)", scopes: []int{4}},
- {line: " }"},
- {line: "}"},
- {line: "func TestIfElse() {"},
- {line: " if x := gret1(); x != 0 {", scopes: []int{1}, vars: []string{"var x int"}},
- {line: " a := 0", scopes: []int{1, 2}, vars: []string{"var a int"}},
- {line: " f1(a); f1(x)", scopes: []int{1, 2}},
- {line: " } else {"},
- {line: " b := 1", scopes: []int{1, 3}, vars: []string{"var b int"}},
- {line: " f1(b); f1(x+1)", scopes: []int{1, 3}},
- {line: " }"},
- {line: "}"},
- {line: "func TestSwitch() {", vars: []string{}},
- {line: " switch x := gret1(); x {", scopes: []int{1}, vars: []string{"var x int"}},
- {line: " case 0:", scopes: []int{1}},
- {line: " i := x + 5", scopes: []int{1, 2}, vars: []string{"var i int"}},
- {line: " f1(x); f1(i)", scopes: []int{1, 2}},
- {line: " case 1:", scopes: []int{1}},
- {line: " j := x + 10", scopes: []int{1, 3}, vars: []string{"var j int"}},
- {line: " f1(x); f1(j)", scopes: []int{1, 3}},
- {line: " case 2:", scopes: []int{1}},
- {line: " k := x + 2", scopes: []int{1, 4}, vars: []string{"var k int"}},
- {line: " f1(x); f1(k)", scopes: []int{1, 4}},
- {line: " }"},
- {line: "}"},
- {line: "func TestTypeSwitch() {", vars: []string{}},
- {line: " switch x := iface.(type) {"},
- {line: " case int:"},
- {line: " f1(x)", scopes: []int{1}, vars: []string{"var x int"}},
- {line: " case uint8:"},
- {line: " f1(int(x))", scopes: []int{2}, vars: []string{"var x uint8"}},
- {line: " case float64:"},
- {line: " f1(int(x)+1)", scopes: []int{3}, vars: []string{"var x float64"}},
- {line: " }"},
- {line: "}"},
- {line: "func TestSelectScope() {"},
- {line: " select {"},
- {line: " case i := <- ch:"},
- {line: " f1(i)", scopes: []int{1}, vars: []string{"var i int"}},
- {line: " case f := <- floatch:"},
- {line: " f1(int(f))", scopes: []int{2}, vars: []string{"var f float64"}},
- {line: " }"},
- {line: "}"},
- {line: "func TestBlock() {", vars: []string{"var a int"}},
- {line: " a := 1"},
- {line: " {"},
- {line: " b := 2", scopes: []int{1}, vars: []string{"var b int"}},
- {line: " f1(b)", scopes: []int{1}},
- {line: " f1(a)", scopes: []int{1}},
- {line: " }"},
- {line: "}"},
- {line: "func TestDiscontiguousRanges() {", vars: []string{"var a int"}},
- {line: " a := 0"},
- {line: " f1(a)"},
- {line: " {"},
- {line: " b := 0", scopes: []int{1}, vars: []string{"var b int"}},
- {line: " f2(b)", scopes: []int{1}},
- {line: " if gretbool() {", scopes: []int{1}},
- {line: " c := 0", scopes: []int{1, 2}, vars: []string{"var c int"}},
- {line: " f3(c)", scopes: []int{1, 2}},
- {line: " } else {"},
- {line: " c := 1.1", scopes: []int{1, 3}, vars: []string{"var c float64"}},
- {line: " f4(int(c))", scopes: []int{1, 3}},
- {line: " }"},
- {line: " f5(b)", scopes: []int{1}},
- {line: " }"},
- {line: " f6(a)"},
- {line: "}"},
- {line: "func TestClosureScope() {", vars: []string{"var a int", "var b int", "var f func(int)"}},
- {line: " a := 1; b := 1"},
- {line: " f := func(c int) {", scopes: []int{0}, vars: []string{"arg c int", "var a int", "var d int"}},
- {line: " d := 3"},
- {line: " f1(a); f1(c); f1(d)"},
- {line: " if e := 3; e != 0 {", scopes: []int{1}, vars: []string{"var e int"}},
- {line: " f1(e)", scopes: []int{1}},
- {line: " }"},
- {line: " }"},
- {line: " f(3); f1(b)"},
- {line: "}"},
- {line: "func main() {"},
- {line: " TestNestedFor()"},
- {line: " TestOas2()"},
- {line: " TestIfElse()"},
- {line: " TestSwitch()"},
- {line: " TestTypeSwitch()"},
- {line: " TestSelectScope()"},
- {line: " TestBlock()"},
- {line: " TestDiscontiguousRanges()"},
- {line: " TestClosureScope()"},
- {line: "}"},
-}
-
-const detailOutput = false
-
-// Compiles testfile checks that the description of lexical blocks emitted
-// by the linker in debug_info, for each function in the main package,
-// corresponds to what we expect it to be.
-func TestScopeRanges(t *testing.T) {
- testenv.MustHaveGoBuild(t)
- dir, err := ioutil.TempDir("", "TestScopeRanges")
- if err != nil {
- t.Fatalf("could not create directory: %v", err)
- }
- defer os.RemoveAll(dir)
-
- src, f := gobuild(t, dir, testfile)
- defer f.Close()
-
- // the compiler uses forward slashes for paths even on windows
- src = strings.Replace(src, "\\", "/", -1)
-
- pcln, err := f.PCLineTable()
- if err != nil {
- t.Fatal(err)
- }
- dwarfData, err := f.DWARF()
- if err != nil {
- t.Fatal(err)
- }
- dwarfReader := dwarfData.Reader()
-
- lines := make(map[line][]*lexblock)
-
- for {
- entry, err := dwarfReader.Next()
- if err != nil {
- t.Fatal(err)
- }
- if entry == nil {
- break
- }
-
- if entry.Tag != dwarf.TagSubprogram {
- continue
- }
-
- name, ok := entry.Val(dwarf.AttrName).(string)
- if !ok || !strings.HasPrefix(name, "main.Test") {
- continue
- }
-
- var scope lexblock
- ctxt := scopexplainContext{
- dwarfData: dwarfData,
- dwarfReader: dwarfReader,
- scopegen: 1,
- }
-
- readScope(&ctxt, &scope, entry)
-
- scope.markLines(pcln, lines)
- }
-
- anyerror := false
- for i := range testfile {
- tgt := testfile[i].scopes
- out := lines[line{src, i + 1}]
-
- if detailOutput {
- t.Logf("%s // %v", testfile[i].line, out)
- }
-
- scopesok := checkScopes(tgt, out)
- if !scopesok {
- t.Logf("mismatch at line %d %q: expected: %v got: %v\n", i, testfile[i].line, tgt, scopesToString(out))
- }
-
- varsok := true
- if testfile[i].vars != nil {
- if len(out) > 0 {
- varsok = checkVars(testfile[i].vars, out[len(out)-1].vars)
- if !varsok {
- t.Logf("variable mismatch at line %d %q for scope %d: expected: %v got: %v\n", i, testfile[i].line, out[len(out)-1].id, testfile[i].vars, out[len(out)-1].vars)
- }
- }
- }
-
- anyerror = anyerror || !scopesok || !varsok
- }
-
- if anyerror {
- t.Fatalf("mismatched output")
- }
-}
-
-func scopesToString(v []*lexblock) string {
- r := make([]string, len(v))
- for i, s := range v {
- r[i] = strconv.Itoa(s.id)
- }
- return "[ " + strings.Join(r, ", ") + " ]"
-}
-
-func checkScopes(tgt []int, out []*lexblock) bool {
- if len(out) > 0 {
- // omit scope 0
- out = out[1:]
- }
- if len(tgt) != len(out) {
- return false
- }
- for i := range tgt {
- if tgt[i] != out[i].id {
- return false
- }
- }
- return true
-}
-
-func checkVars(tgt, out []string) bool {
- if len(tgt) != len(out) {
- return false
- }
- for i := range tgt {
- if tgt[i] != out[i] {
- return false
- }
- }
- return true
-}
-
-type lexblock struct {
- id int
- ranges [][2]uint64
- vars []string
- scopes []lexblock
-}
-
-type line struct {
- file string
- lineno int
-}
-
-type scopexplainContext struct {
- dwarfData *dwarf.Data
- dwarfReader *dwarf.Reader
- scopegen int
- lines map[line][]int
-}
-
-// readScope reads the DW_TAG_lexical_block or the DW_TAG_subprogram in
-// entry and writes a description in scope.
-// Nested DW_TAG_lexical_block entries are read recursively.
-func readScope(ctxt *scopexplainContext, scope *lexblock, entry *dwarf.Entry) {
- if lowpc, ok := entry.Val(dwarf.AttrLowpc).(uint64); ok {
- highpc, _ := entry.Val(dwarf.AttrHighpc).(uint64)
- scope.ranges = [][2]uint64{[2]uint64{lowpc, highpc}}
- } else {
- ranges, err := ctxt.dwarfData.Ranges(entry)
- if err != nil {
- panic(err)
- }
- scope.ranges = ranges
- }
- for {
- e, err := ctxt.dwarfReader.Next()
- if err != nil {
- panic(err)
- }
- switch e.Tag {
- case 0:
- sort.Strings(scope.vars)
- return
- case dwarf.TagFormalParameter:
- typ, err := ctxt.dwarfData.Type(e.Val(dwarf.AttrType).(dwarf.Offset))
- if err != nil {
- panic(err)
- }
- scope.vars = append(scope.vars, "arg "+e.Val(dwarf.AttrName).(string)+" "+typ.String())
- case dwarf.TagVariable:
- typ, err := ctxt.dwarfData.Type(e.Val(dwarf.AttrType).(dwarf.Offset))
- if err != nil {
- panic(err)
- }
- scope.vars = append(scope.vars, "var "+e.Val(dwarf.AttrName).(string)+" "+typ.String())
- case dwarf.TagLexDwarfBlock:
- scope.scopes = append(scope.scopes, lexblock{id: ctxt.scopegen})
- ctxt.scopegen++
- readScope(ctxt, &scope.scopes[len(scope.scopes)-1], e)
- }
- }
-}
-
-// markLines marks all lines that belong to this scope with this scope
-// Recursively calls markLines for all children scopes.
-func (scope *lexblock) markLines(pcln objfile.Liner, lines map[line][]*lexblock) {
- for _, r := range scope.ranges {
- for pc := r[0]; pc < r[1]; pc++ {
- file, lineno, _ := pcln.PCToLine(pc)
- l := line{file, lineno}
- if len(lines[l]) == 0 || lines[l][len(lines[l])-1] != scope {
- lines[l] = append(lines[l], scope)
- }
- }
- }
-
- for i := range scope.scopes {
- scope.scopes[i].markLines(pcln, lines)
- }
-}
-
-func gobuild(t *testing.T, dir string, testfile []testline) (string, *objfile.File) {
- src := filepath.Join(dir, "test.go")
- dst := filepath.Join(dir, "out.o")
-
- f, err := os.Create(src)
- if err != nil {
- t.Fatal(err)
- }
- for i := range testfile {
- f.Write([]byte(testfile[i].line))
- f.Write([]byte{'\n'})
- }
- f.Close()
-
- cmd := exec.Command(testenv.GoToolPath(t), "build", "-gcflags=-N -l", "-o", dst, src)
- if b, err := cmd.CombinedOutput(); err != nil {
- t.Logf("build: %s\n", string(b))
- t.Fatal(err)
- }
-
- pkg, err := objfile.Open(dst)
- if err != nil {
- t.Fatal(err)
- }
- return src, pkg
-}
_32bit uintptr // size on 32bit platforms
_64bit uintptr // size on 64bit platforms
}{
- {Func{}, 112, 192},
+ {Func{}, 96, 160},
{Name{}, 36, 56},
{Param{}, 28, 56},
{Node{}, 84, 136},
lineno = autogeneratedPos
dclcontext = PEXTERN
- markdcl(src.NoPos)
+ markdcl()
this := namedfield(".this", rcvr)
this.Left.Name.Param.Ntype = this.Right
fn.Func.Nname.Name.Param.Ntype = t
fn.Func.Nname.Sym.SetExported(true) // prevent export; see closure.go
declare(fn.Func.Nname, PFUNC)
- funchdr(fn, src.NoPos)
+ funchdr(fn)
// arg list
var args []*Node
dumplist("genwrapper body", fn.Nbody)
}
- funcbody(fn, src.NoPos)
+ funcbody(fn)
Curfn = fn
- popdcl(src.NoPos)
+ popdcl()
if debug_dclstack != 0 {
testdclstack()
}
Shortname *types.Sym
Enter Nodes // for example, allocate and initialize memory for escaping parameters
Exit Nodes
- Cvars Nodes // closure params
- Dcl []*Node // autodcl for this func/closure
- Inldcl Nodes // copy of dcl for use in inlining
- scopes src.Scopes // lexical scopes of the function
+ Cvars Nodes // closure params
+ Dcl []*Node // autodcl for this func/closure
+ Inldcl Nodes // copy of dcl for use in inlining
Closgen int
Outerfunc *Node // outer function (for closure)
FieldTrack map[*types.Sym]struct{}
import (
"cmd/compile/internal/types"
"cmd/internal/obj"
- "cmd/internal/src"
"cmd/internal/sys"
"fmt"
"strings"
oldfn := Curfn
Curfn = nil
- funchdr(fn, src.NoPos)
+ funchdr(fn)
a = nod(n.Op, nil, nil)
a.List.Set(printargs)
fn.Nbody.Set1(a)
- funcbody(fn, src.NoPos)
+ funcbody(fn)
fn = typecheck(fn, Etop)
typecheckslice(fn.Nbody.Slice(), Etop)
package dwarf
import (
- "cmd/internal/src"
- "errors"
"fmt"
)
// InfoPrefix is the prefix for all the symbols containing DWARF info entries.
const InfoPrefix = "go.info."
-// RangePrefix is the prefix for all the symbols containing DWARF range lists.
-const RangePrefix = "go.range."
-
// Sym represents a symbol.
type Sym interface {
- Len() int64
}
// A Var represents a local variable or a function parameter.
Type Sym
}
-// A Scope represents a lexical scope, all variables contained in a scope
-// will only be visible to instructions covered by the scope.
-// Lexical scopes are contiguous in source files but can end up being
-// compiled to discontiguous blocks of instructions in the executable, the
-// Ranges field lists all the blocks of instructions that belong in this
-// scope.
-type Scope struct {
- src.Scope
- Ranges []Range
- Vars []*Var
-}
-
-// A Range represents a half-open interval [Start, End).
-type Range struct {
- Start, End int64
-}
-
-// UnifyRanges merges the list of ranges of c into the list of ranges of s
-func (s *Scope) UnifyRanges(c *Scope) {
- out := make([]Range, 0, len(s.Ranges)+len(c.Ranges))
-
- i, j := 0, 0
- for {
- var cur Range
- if i < len(s.Ranges) && j < len(c.Ranges) {
- if s.Ranges[i].Start < c.Ranges[j].Start {
- cur = s.Ranges[i]
- i++
- } else {
- cur = c.Ranges[j]
- j++
- }
- } else if i < len(s.Ranges) {
- cur = s.Ranges[i]
- i++
- } else if j < len(c.Ranges) {
- cur = c.Ranges[j]
- j++
- } else {
- break
- }
-
- if len(out) == 0 {
- out = append(out, cur)
- } else {
- last := &out[len(out)-1]
- if cur.Start > last.End {
- out = append(out, cur)
- } else if cur.End > last.End {
- last.End = cur.End
- }
- }
- }
-
- s.Ranges = out
-}
-
// A Context specifies how to add data to a Sym.
type Context interface {
PtrSize() int
DW_ABRV_VARIABLE
DW_ABRV_AUTO
DW_ABRV_PARAM
- DW_ABRV_LEXICAL_BLOCK_RANGES
- DW_ABRV_LEXICAL_BLOCK_SIMPLE
DW_ABRV_STRUCTFIELD
DW_ABRV_FUNCTYPEPARAM
DW_ABRV_DOTDOTDOT
},
},
- /* LEXICAL_BLOCK_RANGES */
- {
- DW_TAG_lexical_block,
- DW_CHILDREN_yes,
- []dwAttrForm{
- {DW_AT_ranges, DW_FORM_data4}, // replace with DW_FORM_sec_offset in DWARFv4.
- },
- },
-
- /* LEXICAL_BLOCK_SIMPLE */
- {
- DW_TAG_lexical_block,
- DW_CHILDREN_yes,
- []dwAttrForm{
- {DW_AT_low_pc, DW_FORM_addr},
- {DW_AT_high_pc, DW_FORM_addr},
- },
- },
-
/* STRUCTFIELD */
{
DW_TAG_member,
ctxt.AddInt(s, 2, value)
case DW_FORM_data4: // constant, {line,loclist,mac,rangelist}ptr
- if cls == DW_CLS_PTR { // DW_AT_stmt_list and DW_AT_ranges
- ctxt.AddSectionOffset(s, 4, data, value)
+ if cls == DW_CLS_PTR { // DW_AT_stmt_list
+ ctxt.AddSectionOffset(s, 4, data, 0)
break
}
ctxt.AddInt(s, 4, value)
ctxt.AddInt(s, 1, 0)
}
- // In DWARF 3 the ref_addr is always 32 bits, unless emitting a large
+ // In DWARF 2 (which is what we claim to generate),
+ // the ref_addr is the same size as a normal address.
+ // In DWARF 3 it is always 32 bits, unless emitting a large
// (> 4 GB of debug info aka "64-bit") unit, which we don't implement.
case DW_FORM_ref_addr: // reference to a DIE in the .info section
if data == nil {
return fmt.Errorf("dwarf: null reference in %d", abbrev)
} else {
- ctxt.AddSectionOffset(s, 4, data, 0)
+ ctxt.AddSectionOffset(s, ctxt.PtrSize(), data, 0)
}
case DW_FORM_ref1, // reference within the compilation unit
// PutFunc writes a DIE for a function to s.
// It also writes child DIEs for each variable in vars.
-func PutFunc(ctxt Context, s, ranges Sym, name string, external bool, startPC Sym, size int64, scopes []Scope) error {
+func PutFunc(ctxt Context, s Sym, name string, external bool, startPC Sym, size int64, vars []*Var) {
Uleb128put(ctxt, s, DW_ABRV_FUNCTION)
putattr(ctxt, s, DW_ABRV_FUNCTION, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
putattr(ctxt, s, DW_ABRV_FUNCTION, DW_FORM_addr, DW_CLS_ADDRESS, 0, startPC)
ev = 1
}
putattr(ctxt, s, DW_ABRV_FUNCTION, DW_FORM_flag, DW_CLS_FLAG, ev, 0)
- if len(scopes) > 0 {
- var encbuf [20]byte
- if putscope(ctxt, s, ranges, startPC, 0, scopes, encbuf[:0]) < int32(len(scopes)) {
- return errors.New("multiple toplevel scopes")
- }
- }
-
- Uleb128put(ctxt, s, 0)
- return nil
-}
-
-func putvar(ctxt Context, s Sym, v *Var, encbuf []byte) {
- n := v.Name
-
- Uleb128put(ctxt, s, int64(v.Abbrev))
- putattr(ctxt, s, v.Abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n)
- loc := append(encbuf[:0], DW_OP_call_frame_cfa)
- if v.Offset != 0 {
- loc = append(loc, DW_OP_consts)
- loc = AppendSleb128(loc, int64(v.Offset))
- loc = append(loc, DW_OP_plus)
- }
- putattr(ctxt, s, v.Abbrev, DW_FORM_block1, DW_CLS_BLOCK, int64(len(loc)), loc)
- putattr(ctxt, s, v.Abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type)
-}
-
-func putscope(ctxt Context, s, ranges Sym, startPC Sym, curscope int32, scopes []Scope, encbuf []byte) int32 {
- for _, v := range scopes[curscope].Vars {
- putvar(ctxt, s, v, encbuf)
- }
- this := curscope
- curscope++
- for curscope < int32(len(scopes)) {
- scope := scopes[curscope]
- if scope.Parent != this {
- return curscope
- }
-
- emptyscope := len(scope.Vars) == 0 || len(scope.Ranges) == 0
-
- if !emptyscope {
- if len(scope.Ranges) == 1 {
- Uleb128put(ctxt, s, DW_ABRV_LEXICAL_BLOCK_SIMPLE)
- putattr(ctxt, s, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].Start, startPC)
- putattr(ctxt, s, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].End, startPC)
- } else {
- Uleb128put(ctxt, s, DW_ABRV_LEXICAL_BLOCK_RANGES)
- putattr(ctxt, s, DW_ABRV_LEXICAL_BLOCK_RANGES, DW_FORM_data4, DW_CLS_PTR, ranges.Len(), ranges)
- ctxt.AddAddress(ranges, nil, -1)
- ctxt.AddAddress(ranges, startPC, 0)
- for _, pcrange := range scope.Ranges {
- ctxt.AddAddress(ranges, nil, pcrange.Start)
- ctxt.AddAddress(ranges, nil, pcrange.End)
- }
- ctxt.AddAddress(ranges, nil, 0)
- ctxt.AddAddress(ranges, nil, 0)
- }
+ names := make(map[string]bool)
+ var encbuf [20]byte
+ for _, v := range vars {
+ var n string
+ if names[v.Name] {
+ n = fmt.Sprintf("%s#%d", v.Name, len(names))
+ } else {
+ n = v.Name
}
-
- curscope = putscope(ctxt, s, ranges, startPC, curscope, scopes, encbuf)
-
- if !emptyscope {
- Uleb128put(ctxt, s, 0)
+ names[n] = true
+
+ Uleb128put(ctxt, s, int64(v.Abbrev))
+ putattr(ctxt, s, v.Abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n)
+ loc := append(encbuf[:0], DW_OP_call_frame_cfa)
+ if v.Offset != 0 {
+ loc = append(loc, DW_OP_consts)
+ loc = AppendSleb128(loc, int64(v.Offset))
+ loc = append(loc, DW_OP_plus)
}
+ putattr(ctxt, s, v.Abbrev, DW_FORM_block1, DW_CLS_BLOCK, int64(len(loc)), loc)
+ putattr(ctxt, s, v.Abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type)
}
- return curscope
+ Uleb128put(ctxt, s, 0)
}
// VarsByOffset attaches the methods of sort.Interface to []*Var,
// WriteAddr writes an address of size siz into s at offset off.
// rsym and roff specify the relocation for the address.
func (s *LSym) WriteAddr(ctxt *Link, off int64, siz int, rsym *LSym, roff int64) {
- if siz != ctxt.Arch.PtrSize && siz != 4 {
+ if siz != ctxt.Arch.PtrSize {
ctxt.Diag("WriteAddr: bad address size %d in %s", siz, s.Name)
}
s.prepwrite(ctxt, off, siz)
SHOSTOBJ
SDWARFSECT
SDWARFINFO
- SDWARFRANGE
SSUB = SymKind(1 << 8)
SMASK = SymKind(SSUB - 1)
SHIDDEN = SymKind(1 << 9)
Armsize int32
Pc int64
DiagFunc func(string, ...interface{})
- DebugInfo func(fn *LSym, curfn interface{}) []dwarf.Scope // if non-nil, curfn is a *gc.Node
+ DebugInfo func(fn *LSym, curfn interface{}) []*dwarf.Var // if non-nil, curfn is a *gc.Node
Cursym *LSym
Version int
Errors int
return 0
}
func (c dwCtxt) AddAddress(s dwarf.Sym, data interface{}, value int64) {
+ rsym := data.(*LSym)
ls := s.(*LSym)
size := c.PtrSize()
- if data != nil {
- rsym := data.(*LSym)
- ls.WriteAddr(c.Link, ls.Size, size, rsym, value)
- } else {
- ls.WriteInt(c.Link, ls.Size, size, value)
- }
+ ls.WriteAddr(c.Link, ls.Size, size, rsym, value)
}
func (c dwCtxt) AddSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64) {
ls := s.(*LSym)
r.Type = R_DWARFREF
}
-func (s *LSym) Len() int64 {
- return s.Size
-}
-
// makeFuncDebugEntry makes a DWARF Debugging Information Entry
// for TEXT symbol s.
func makeFuncDebugEntry(ctxt *Link, curfn interface{}, s *LSym) {
}
dsym.Type = SDWARFINFO
dsym.Set(AttrDuplicateOK, s.DuplicateOK())
-
- drsym := ctxt.Lookup(dwarf.RangePrefix+s.Name, int(s.Version))
- if drsym.Size != 0 {
- return
- }
- drsym.Type = SDWARFRANGE
- drsym.Set(AttrDuplicateOK, s.DuplicateOK())
-
- var scopes []dwarf.Scope
+ var vars []*dwarf.Var
if ctxt.DebugInfo != nil {
- scopes = ctxt.DebugInfo(s, curfn)
- }
- err := dwarf.PutFunc(dwCtxt{ctxt}, dsym, drsym, s.Name, s.Version == 0, s, s.Size, scopes)
- if err != nil {
- ctxt.Diag("emitting DWARF for %s failed: %v", s.Name, err)
+ vars = ctxt.DebugInfo(s, curfn)
}
- ctxt.Data = append(ctxt.Data, dsym, drsym)
+ dwarf.PutFunc(dwCtxt{ctxt}, dsym, s.Name, s.Version == 0, s, s.Size, vars)
+ ctxt.Data = append(ctxt.Data, dsym)
}
+++ /dev/null
-// Copyright 2017 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package src
-
-// Scope represents a lexical scope.
-type Scope struct {
- Start, End XPos
- Parent int32
-}
-
-// Scopes represents a tree of lexical scopes
-type Scopes struct {
- Scopes []Scope // lexical scopes
- curscope int32 // current scope index (during noding)
-}
-
-// Open starts a new scope, scopes.Curscope is the parent.
-func (scopes *Scopes) Open(posTable *PosTable, pos Pos) {
- scope := Scope{Parent: scopes.curscope, Start: NoXPos, End: NoXPos}
- if pos.IsKnown() {
- scope.Start = posTable.XPos(pos)
- }
- scopes.Scopes = append(scopes.Scopes, scope)
- scopes.curscope = int32(len(scopes.Scopes) - 1)
-}
-
-// Close ends the current scope.
-func (scopes *Scopes) Close(posTable *PosTable, pos Pos) {
- scope := &scopes.Scopes[scopes.curscope]
- if pos.IsKnown() {
- scope.End = posTable.XPos(pos)
- }
- scopes.curscope = scope.Parent
-}
}
case obj.R_DWARFREF:
- sectName := ""
- vaddr := int64(0)
- if r.Sym.Sect != nil {
- sectName = r.Sym.Sect.Name
- vaddr = int64(r.Sym.Sect.Vaddr)
- } else if r.Sym.Type == obj.SDWARFRANGE {
- sectName = ".debug_ranges"
- vaddr = 0
- } else {
+ if r.Sym.Sect == nil {
Errorf(s, "missing DWARF section for relocation target %s", r.Sym.Name)
}
-
if Linkmode == LinkExternal {
r.Done = 0
// PE code emits IMAGE_REL_I386_SECREL and IMAGE_REL_AMD64_SECREL
r.Type = obj.R_ADDR
}
- r.Xsym = ctxt.Syms.ROLookup(sectName, 0)
- r.Xadd = r.Add + Symaddr(r.Sym) - vaddr
-
+ r.Xsym = ctxt.Syms.ROLookup(r.Sym.Sect.Name, 0)
+ r.Xadd = r.Add + Symaddr(r.Sym) - int64(r.Sym.Sect.Vaddr)
o = r.Xadd
rs = r.Xsym
if Iself && SysArch.Family == sys.AMD64 {
}
break
}
- o = Symaddr(r.Sym) + r.Add - vaddr
+ o = Symaddr(r.Sym) + r.Add - int64(r.Sym.Sect.Vaddr)
case obj.R_WEAKADDROFF:
if !r.Sym.Attr.Reachable() {
if s.Type != obj.SDWARFSECT {
break
}
-
sect = addsection(&Segdwarf, s.Name, 04)
sect.Align = 1
datsize = Rnd(datsize, int64(sect.Align))
// - assign global variables and types to their packages
// - gdb uses c syntax, meaning clumsy quoting is needed for go identifiers. eg
// ptype struct '[]uint8' and qualifiers need to be quoted away
+// - lexical scoping is lost, so gdb gets confused as to which 'main.i' you mean.
// - file:line info for variables
// - make strings a typedef so prettyprinters can see the underlying string type
var framesec *Symbol
var infosec *Symbol
var linesec *Symbol
-var rangesec *Symbol
var gdbscript string
return syms
}
-func writeranges(ctxt *Link, syms []*Symbol) []*Symbol {
- if rangesec == nil {
- rangesec = ctxt.Syms.Lookup(".debug_ranges", 0)
- }
- rangesec.Type = obj.SDWARFSECT
- rangesec.Attr |= AttrReachable
- rangesec.R = rangesec.R[:0]
-
- for _, s := range ctxt.Textp {
- rangeSym := ctxt.Syms.Lookup(dwarf.RangePrefix+s.Name, int(s.Version))
- rangeSym.Attr |= AttrHidden
- rangeSym.Attr |= AttrReachable
- rangeSym.Type = obj.SDWARFRANGE
- rangeSym.Value = rangesec.Size
- rangesec.P = append(rangesec.P, rangeSym.P...)
- for _, r := range rangeSym.R {
- r.Off += int32(rangesec.Size)
- rangesec.R = append(rangesec.R, r)
- }
- rangesec.Size += rangeSym.Size
- }
- if rangesec.Size > 0 {
- // PE does not like empty sections
- syms = append(syms, rangesec)
- }
- return syms
-}
-
/*
* Walk DWarfDebugInfoEntries, and emit .debug_info
*/
// Fields marked with (*) must be changed for 64-bit dwarf
// This must match COMPUNITHEADERSIZE above.
Adduint32(ctxt, s, 0) // unit_length (*), will be filled in later.
- Adduint16(ctxt, s, 3) // dwarf version (appendix F)
+ Adduint16(ctxt, s, 2) // dwarf version (appendix F)
// debug_abbrev_offset (*)
adddwarfref(ctxt, s, abbrevsym, 4)
syms := writeabbrev(ctxt, nil)
syms, funcs := writelines(ctxt, syms)
syms = writeframes(ctxt, syms)
- syms = writeranges(ctxt, syms)
synthesizestringtypes(ctxt, dwtypes.Child)
synthesizeslicetypes(ctxt, dwtypes.Child)
Addstring(shstrtab, ".debug_pubnames")
Addstring(shstrtab, ".debug_pubtypes")
Addstring(shstrtab, ".debug_gdb_scripts")
- Addstring(shstrtab, ".debug_ranges")
if Linkmode == LinkExternal {
Addstring(shstrtab, elfRelType+".debug_info")
Addstring(shstrtab, elfRelType+".debug_aranges")
putelfsectionsym(sym, sym.Sect.Elfsect.shnum)
sym = ctxt.Syms.Lookup(".debug_frame", 0)
putelfsectionsym(sym, sym.Sect.Elfsect.shnum)
- sym = ctxt.Syms.Lookup(".debug_ranges", 0)
- if sym.Sect != nil {
- putelfsectionsym(sym, sym.Sect.Elfsect.shnum)
- }
}
/*
}
}
-func (s *Symbol) Len() int64 {
- return s.Size
-}
-
// Attribute is a set of common symbol attributes.
type Attribute int16