2015-02-27 22:57:28 -05:00
|
|
|
// Copyright 2010 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.
|
|
|
|
|
|
2015-03-05 13:57:36 -05:00
|
|
|
// TODO/NICETOHAVE:
|
|
|
|
|
// - eliminate DW_CLS_ if not used
|
|
|
|
|
// - package info in compilation units
|
|
|
|
|
// - 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
|
|
|
|
|
// - file:line info for variables
|
|
|
|
|
// - make strings a typedef so prettyprinters can see the underlying string type
|
|
|
|
|
|
2015-02-27 22:57:28 -05:00
|
|
|
package ld
|
|
|
|
|
|
|
|
|
|
import (
|
2016-07-28 13:04:41 -04:00
|
|
|
"cmd/internal/dwarf"
|
2017-04-18 12:53:25 -07:00
|
|
|
"cmd/internal/objabi"
|
2015-02-27 22:57:28 -05:00
|
|
|
"fmt"
|
2016-03-14 09:23:04 -07:00
|
|
|
"log"
|
2015-04-08 12:55:34 -07:00
|
|
|
"os"
|
2015-02-27 22:57:28 -05:00
|
|
|
"strings"
|
|
|
|
|
)
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
type dwctxt struct {
|
|
|
|
|
linkctxt *Link
|
|
|
|
|
}
|
2016-03-14 09:23:04 -07:00
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
func (c dwctxt) PtrSize() int {
|
2016-07-28 13:04:41 -04:00
|
|
|
return SysArch.PtrSize
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2016-08-19 22:40:38 -04:00
|
|
|
func (c dwctxt) AddInt(s dwarf.Sym, size int, i int64) {
|
2016-08-19 11:35:54 -04:00
|
|
|
ls := s.(*Symbol)
|
2016-08-19 22:40:38 -04:00
|
|
|
adduintxx(c.linkctxt, ls, uint64(i), size)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2016-08-19 22:40:38 -04:00
|
|
|
func (c dwctxt) AddBytes(s dwarf.Sym, b []byte) {
|
2016-08-19 11:35:54 -04:00
|
|
|
ls := s.(*Symbol)
|
2016-09-20 15:31:26 +12:00
|
|
|
Addbytes(ls, b)
|
2016-07-28 13:04:41 -04:00
|
|
|
}
|
2016-08-19 22:40:38 -04:00
|
|
|
func (c dwctxt) AddString(s dwarf.Sym, v string) {
|
2016-09-20 15:31:26 +12:00
|
|
|
Addstring(s.(*Symbol), v)
|
2016-07-28 13:04:41 -04:00
|
|
|
}
|
2016-08-19 22:40:38 -04:00
|
|
|
func (c dwctxt) SymValue(s dwarf.Sym) int64 {
|
2016-08-19 11:35:54 -04:00
|
|
|
return s.(*Symbol).Value
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
func (c dwctxt) AddAddress(s dwarf.Sym, data interface{}, value int64) {
|
2016-07-28 13:04:41 -04:00
|
|
|
if value != 0 {
|
2016-08-19 11:35:54 -04:00
|
|
|
value -= (data.(*Symbol)).Value
|
2016-07-28 13:04:41 -04:00
|
|
|
}
|
2016-08-19 22:40:38 -04:00
|
|
|
Addaddrplus(c.linkctxt, s.(*Symbol), data.(*Symbol), value)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
func (c dwctxt) AddSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64) {
|
2016-08-19 11:35:54 -04:00
|
|
|
ls := s.(*Symbol)
|
2016-07-28 13:04:41 -04:00
|
|
|
switch size {
|
|
|
|
|
default:
|
2016-09-17 09:39:33 -04:00
|
|
|
Errorf(ls, "invalid size %d in adddwarfref\n", size)
|
2016-07-28 13:04:41 -04:00
|
|
|
fallthrough
|
|
|
|
|
case SysArch.PtrSize:
|
2016-08-19 22:40:38 -04:00
|
|
|
Addaddr(c.linkctxt, ls, t.(*Symbol))
|
2016-07-28 13:04:41 -04:00
|
|
|
case 4:
|
2016-08-19 22:40:38 -04:00
|
|
|
addaddrplus4(c.linkctxt, ls, t.(*Symbol), 0)
|
2016-07-28 13:04:41 -04:00
|
|
|
}
|
|
|
|
|
r := &ls.R[len(ls.R)-1]
|
2017-04-18 12:53:25 -07:00
|
|
|
r.Type = objabi.R_DWARFREF
|
2016-07-28 13:04:41 -04:00
|
|
|
r.Add = ofs
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
var gdbscript string
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-04-22 10:31:14 +12:00
|
|
|
var dwarfp []*Symbol
|
2016-03-14 09:23:04 -07:00
|
|
|
|
2017-05-22 20:17:31 -04:00
|
|
|
func writeabbrev(ctxt *Link) *Symbol {
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
s := ctxt.Syms.Lookup(".debug_abbrev", 0)
|
2017-04-19 15:15:35 +12:00
|
|
|
s.Type = SDWARFSECT
|
2016-09-20 15:31:26 +12:00
|
|
|
Addbytes(s, dwarf.GetAbbrev())
|
2017-05-22 20:17:31 -04:00
|
|
|
return s
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Root DIEs for compilation units, types and global variables.
|
|
|
|
|
*/
|
2016-07-28 13:04:41 -04:00
|
|
|
var dwroot dwarf.DWDie
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
var dwtypes dwarf.DWDie
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
var dwglobals dwarf.DWDie
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
func newattr(die *dwarf.DWDie, attr uint16, cls int, value int64, data interface{}) *dwarf.DWAttr {
|
|
|
|
|
a := new(dwarf.DWAttr)
|
|
|
|
|
a.Link = die.Attr
|
|
|
|
|
die.Attr = a
|
|
|
|
|
a.Atr = attr
|
|
|
|
|
a.Cls = uint8(cls)
|
|
|
|
|
a.Value = value
|
|
|
|
|
a.Data = data
|
2015-02-27 22:57:28 -05:00
|
|
|
return a
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Each DIE (except the root ones) has at least 1 attribute: its
|
|
|
|
|
// name. getattr moves the desired one to the front so
|
|
|
|
|
// frequently searched ones are found faster.
|
2016-07-28 13:04:41 -04:00
|
|
|
func getattr(die *dwarf.DWDie, attr uint16) *dwarf.DWAttr {
|
|
|
|
|
if die.Attr.Atr == attr {
|
|
|
|
|
return die.Attr
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
a := die.Attr
|
|
|
|
|
b := a.Link
|
2015-02-27 22:57:28 -05:00
|
|
|
for b != nil {
|
2016-07-28 13:04:41 -04:00
|
|
|
if b.Atr == attr {
|
|
|
|
|
a.Link = b.Link
|
|
|
|
|
b.Link = die.Attr
|
|
|
|
|
die.Attr = b
|
2015-02-27 22:57:28 -05:00
|
|
|
return b
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
a = b
|
2016-07-28 13:04:41 -04:00
|
|
|
b = b.Link
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
// Every DIE has at least a AT_name attribute (but it will only be
|
2016-03-14 09:23:04 -07:00
|
|
|
// written out if it is listed in the abbrev).
|
2016-08-19 22:40:38 -04:00
|
|
|
func newdie(ctxt *Link, parent *dwarf.DWDie, abbrev int, name string, version int) *dwarf.DWDie {
|
2016-07-28 13:04:41 -04:00
|
|
|
die := new(dwarf.DWDie)
|
|
|
|
|
die.Abbrev = abbrev
|
|
|
|
|
die.Link = parent.Child
|
|
|
|
|
parent.Child = die
|
|
|
|
|
|
|
|
|
|
newattr(die, dwarf.DW_AT_name, dwarf.DW_CLS_STRING, int64(len(name)), name)
|
|
|
|
|
|
|
|
|
|
if name != "" && (abbrev <= dwarf.DW_ABRV_VARIABLE || abbrev >= dwarf.DW_ABRV_NULLTYPE) {
|
|
|
|
|
if abbrev != dwarf.DW_ABRV_VARIABLE || version == 0 {
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
sym := ctxt.Syms.Lookup(dwarf.InfoPrefix+name, version)
|
2017-04-28 12:22:50 +12:00
|
|
|
sym.Attr |= AttrNotInSymbolTable
|
2017-04-19 15:15:35 +12:00
|
|
|
sym.Type = SDWARFINFO
|
2016-07-28 13:04:41 -04:00
|
|
|
die.Sym = sym
|
2016-03-14 09:23:04 -07:00
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return die
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
func walktypedef(die *dwarf.DWDie) *dwarf.DWDie {
|
|
|
|
|
if die == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
// Resolve typedef if present.
|
2016-07-28 13:04:41 -04:00
|
|
|
if die.Abbrev == dwarf.DW_ABRV_TYPEDECL {
|
|
|
|
|
for attr := die.Attr; attr != nil; attr = attr.Link {
|
|
|
|
|
if attr.Atr == dwarf.DW_AT_type && attr.Cls == dwarf.DW_CLS_REFERENCE && attr.Data != nil {
|
|
|
|
|
return attr.Data.(*dwarf.DWDie)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return die
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
func walksymtypedef(ctxt *Link, s *Symbol) *Symbol {
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
if t := ctxt.Syms.ROLookup(s.Name+"..def", int(s.Version)); t != nil {
|
2016-03-14 09:23:04 -07:00
|
|
|
return t
|
|
|
|
|
}
|
|
|
|
|
return s
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-27 22:57:28 -05:00
|
|
|
// Find child by AT_name using hashtable if available or linear scan
|
|
|
|
|
// if not.
|
2016-07-28 13:04:41 -04:00
|
|
|
func findchild(die *dwarf.DWDie, name string) *dwarf.DWDie {
|
|
|
|
|
var prev *dwarf.DWDie
|
2015-10-10 10:57:35 +00:00
|
|
|
for ; die != prev; prev, die = die, walktypedef(die) {
|
2016-07-28 13:04:41 -04:00
|
|
|
for a := die.Child; a != nil; a = a.Link {
|
|
|
|
|
if name == getattr(a, dwarf.DW_AT_name).Data {
|
2016-03-14 09:23:04 -07:00
|
|
|
return a
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2015-10-10 10:57:35 +00:00
|
|
|
}
|
2016-03-14 09:23:04 -07:00
|
|
|
continue
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-07 18:00:57 +03:00
|
|
|
// Used to avoid string allocation when looking up dwarf symbols
|
2016-07-28 13:04:41 -04:00
|
|
|
var prefixBuf = []byte(dwarf.InfoPrefix)
|
2016-04-07 18:00:57 +03:00
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
func find(ctxt *Link, name string) *Symbol {
|
2016-04-07 18:00:57 +03:00
|
|
|
n := append(prefixBuf, name...)
|
|
|
|
|
// The string allocation below is optimized away because it is only used in a map lookup.
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
s := ctxt.Syms.ROLookup(string(n), 0)
|
2016-07-28 13:04:41 -04:00
|
|
|
prefixBuf = n[:len(dwarf.InfoPrefix)]
|
2017-04-19 15:15:35 +12:00
|
|
|
if s != nil && s.Type == SDWARFINFO {
|
2016-07-28 13:04:41 -04:00
|
|
|
return s
|
|
|
|
|
}
|
|
|
|
|
return nil
|
2016-03-14 09:23:04 -07:00
|
|
|
}
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
func mustFind(ctxt *Link, name string) *Symbol {
|
|
|
|
|
r := find(ctxt, name)
|
2015-02-27 22:57:28 -05:00
|
|
|
if r == nil {
|
2016-03-14 09:23:04 -07:00
|
|
|
Exitf("dwarf find: cannot find %s", name)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
return r
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-19 11:35:54 -04:00
|
|
|
func adddwarfref(ctxt *Link, s *Symbol, t *Symbol, size int) int64 {
|
2016-03-14 09:23:04 -07:00
|
|
|
var result int64
|
|
|
|
|
switch size {
|
2015-02-27 22:57:28 -05:00
|
|
|
default:
|
2016-09-17 09:39:33 -04:00
|
|
|
Errorf(s, "invalid size %d in adddwarfref\n", size)
|
2016-03-14 09:23:04 -07:00
|
|
|
fallthrough
|
2016-04-06 12:01:40 -07:00
|
|
|
case SysArch.PtrSize:
|
2016-03-14 09:23:04 -07:00
|
|
|
result = Addaddr(ctxt, s, t)
|
|
|
|
|
case 4:
|
|
|
|
|
result = addaddrplus4(ctxt, s, t, 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2016-03-14 09:23:04 -07:00
|
|
|
r := &s.R[len(s.R)-1]
|
2017-04-18 12:53:25 -07:00
|
|
|
r.Type = objabi.R_DWARFREF
|
2016-03-14 09:23:04 -07:00
|
|
|
return result
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-08-19 11:35:54 -04:00
|
|
|
func newrefattr(die *dwarf.DWDie, attr uint16, ref *Symbol) *dwarf.DWAttr {
|
2015-02-27 22:57:28 -05:00
|
|
|
if ref == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
2016-07-28 13:04:41 -04:00
|
|
|
return newattr(die, attr, dwarf.DW_CLS_REFERENCE, 0, ref)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
func putdies(linkctxt *Link, ctxt dwarf.Context, syms []*Symbol, die *dwarf.DWDie) []*Symbol {
|
2016-07-28 13:04:41 -04:00
|
|
|
for ; die != nil; die = die.Link {
|
2016-08-19 22:40:38 -04:00
|
|
|
syms = putdie(linkctxt, ctxt, syms, die)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2016-08-19 22:40:38 -04:00
|
|
|
Adduint8(linkctxt, syms[len(syms)-1], 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
return syms
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-08-19 11:35:54 -04:00
|
|
|
func dtolsym(s dwarf.Sym) *Symbol {
|
2016-07-28 13:04:41 -04:00
|
|
|
if s == nil {
|
|
|
|
|
return nil
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2016-08-19 11:35:54 -04:00
|
|
|
return s.(*Symbol)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
func putdie(linkctxt *Link, ctxt dwarf.Context, syms []*Symbol, die *dwarf.DWDie) []*Symbol {
|
2016-07-28 13:04:41 -04:00
|
|
|
s := dtolsym(die.Sym)
|
2016-03-14 09:23:04 -07:00
|
|
|
if s == nil {
|
2016-07-28 13:04:41 -04:00
|
|
|
s = syms[len(syms)-1]
|
2016-03-14 09:23:04 -07:00
|
|
|
} else {
|
|
|
|
|
if s.Attr.OnList() {
|
|
|
|
|
log.Fatalf("symbol %s listed multiple times", s.Name)
|
|
|
|
|
}
|
|
|
|
|
s.Attr |= AttrOnList
|
2016-07-28 13:04:41 -04:00
|
|
|
syms = append(syms, s)
|
2016-03-14 09:23:04 -07:00
|
|
|
}
|
2016-07-28 13:04:41 -04:00
|
|
|
dwarf.Uleb128put(ctxt, s, int64(die.Abbrev))
|
|
|
|
|
dwarf.PutAttrs(ctxt, s, die.Abbrev, die.Attr)
|
|
|
|
|
if dwarf.HasChildren(die) {
|
2016-08-19 22:40:38 -04:00
|
|
|
return putdies(linkctxt, ctxt, syms, die.Child)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2016-07-28 13:04:41 -04:00
|
|
|
return syms
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
func reverselist(list **dwarf.DWDie) {
|
2015-03-02 12:35:15 -05:00
|
|
|
curr := *list
|
2016-07-28 13:04:41 -04:00
|
|
|
var prev *dwarf.DWDie
|
2015-02-27 22:57:28 -05:00
|
|
|
for curr != nil {
|
2016-07-28 13:04:41 -04:00
|
|
|
var next *dwarf.DWDie = curr.Link
|
|
|
|
|
curr.Link = prev
|
2015-02-27 22:57:28 -05:00
|
|
|
prev = curr
|
|
|
|
|
curr = next
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*list = prev
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
func reversetree(list **dwarf.DWDie) {
|
2015-02-27 22:57:28 -05:00
|
|
|
reverselist(list)
|
2016-07-28 13:04:41 -04:00
|
|
|
for die := *list; die != nil; die = die.Link {
|
|
|
|
|
if dwarf.HasChildren(die) {
|
|
|
|
|
reversetree(&die.Child)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
func newmemberoffsetattr(die *dwarf.DWDie, offs int32) {
|
2015-02-27 22:57:28 -05:00
|
|
|
var block [20]byte
|
2016-07-28 13:04:41 -04:00
|
|
|
b := append(block[:0], dwarf.DW_OP_plus_uconst)
|
|
|
|
|
b = dwarf.AppendUleb128(b, uint64(offs))
|
|
|
|
|
newattr(die, dwarf.DW_AT_data_member_location, dwarf.DW_CLS_BLOCK, int64(len(b)), b)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
// GDB doesn't like FORM_addr for AT_location, so emit a
|
2015-02-27 22:57:28 -05:00
|
|
|
// location expression that evals to a const.
|
2016-08-19 11:35:54 -04:00
|
|
|
func newabslocexprattr(die *dwarf.DWDie, addr int64, sym *Symbol) {
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(die, dwarf.DW_AT_location, dwarf.DW_CLS_ADDRESS, addr, sym)
|
2015-02-27 22:57:28 -05:00
|
|
|
// below
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Lookup predefined types
|
2016-08-22 10:33:13 -04:00
|
|
|
func lookupOrDiag(ctxt *Link, n string) *Symbol {
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
s := ctxt.Syms.ROLookup(n, 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
if s == nil || s.Size == 0 {
|
2015-04-09 07:37:17 -04:00
|
|
|
Exitf("dwarf: missing type: %s", n)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return s
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
func dotypedef(ctxt *Link, parent *dwarf.DWDie, name string, def *dwarf.DWDie) {
|
2015-02-27 22:57:28 -05:00
|
|
|
// Only emit typedefs for real names.
|
|
|
|
|
if strings.HasPrefix(name, "map[") {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if strings.HasPrefix(name, "struct {") {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if strings.HasPrefix(name, "chan ") {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if name[0] == '[' || name[0] == '*' {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if def == nil {
|
2016-09-17 09:39:33 -04:00
|
|
|
Errorf(nil, "dwarf: bad def in dotypedef")
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
sym := ctxt.Syms.Lookup(dtolsym(def.Sym).Name+"..def", 0)
|
2017-04-28 12:22:50 +12:00
|
|
|
sym.Attr |= AttrNotInSymbolTable
|
2017-04-19 15:15:35 +12:00
|
|
|
sym.Type = SDWARFINFO
|
2016-07-28 13:04:41 -04:00
|
|
|
def.Sym = sym
|
2016-03-14 09:23:04 -07:00
|
|
|
|
2015-02-27 22:57:28 -05:00
|
|
|
// The typedef entry must be created after the def,
|
|
|
|
|
// so that future lookups will find the typedef instead
|
|
|
|
|
// of the real definition. This hooks the typedef into any
|
|
|
|
|
// circular definition loops, so that gdb can understand them.
|
2016-08-19 22:40:38 -04:00
|
|
|
die := newdie(ctxt, parent, dwarf.DW_ABRV_TYPEDECL, name, 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
newrefattr(die, dwarf.DW_AT_type, sym)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Define gotype, for composite ones recurse into constituents.
|
2016-08-19 22:40:38 -04:00
|
|
|
func defgotype(ctxt *Link, gotype *Symbol) *Symbol {
|
2015-02-27 22:57:28 -05:00
|
|
|
if gotype == nil {
|
2016-08-19 22:40:38 -04:00
|
|
|
return mustFind(ctxt, "<unspecified>")
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !strings.HasPrefix(gotype.Name, "type.") {
|
2016-09-17 09:39:33 -04:00
|
|
|
Errorf(gotype, "dwarf: type name doesn't start with \"type.\"")
|
2016-08-19 22:40:38 -04:00
|
|
|
return mustFind(ctxt, "<unspecified>")
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 12:35:15 -05:00
|
|
|
name := gotype.Name[5:] // could also decode from Type.string
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
sdie := find(ctxt, name)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-03-14 09:23:04 -07:00
|
|
|
if sdie != nil {
|
|
|
|
|
return sdie
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
return newtype(ctxt, gotype).Sym.(*Symbol)
|
2016-03-14 09:23:04 -07:00
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
func newtype(ctxt *Link, gotype *Symbol) *dwarf.DWDie {
|
2016-03-14 09:23:04 -07:00
|
|
|
name := gotype.Name[5:] // could also decode from Type.string
|
2016-08-22 10:33:13 -04:00
|
|
|
kind := decodetypeKind(gotype)
|
|
|
|
|
bytesize := decodetypeSize(ctxt.Arch, gotype)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
var die *dwarf.DWDie
|
2015-02-27 22:57:28 -05:00
|
|
|
switch kind {
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.KindBool:
|
2016-08-19 22:40:38 -04:00
|
|
|
die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0)
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_boolean, 0)
|
|
|
|
|
newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.KindInt,
|
|
|
|
|
objabi.KindInt8,
|
|
|
|
|
objabi.KindInt16,
|
|
|
|
|
objabi.KindInt32,
|
|
|
|
|
objabi.KindInt64:
|
2016-08-19 22:40:38 -04:00
|
|
|
die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0)
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_signed, 0)
|
|
|
|
|
newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.KindUint,
|
|
|
|
|
objabi.KindUint8,
|
|
|
|
|
objabi.KindUint16,
|
|
|
|
|
objabi.KindUint32,
|
|
|
|
|
objabi.KindUint64,
|
|
|
|
|
objabi.KindUintptr:
|
2016-08-19 22:40:38 -04:00
|
|
|
die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0)
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_unsigned, 0)
|
|
|
|
|
newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.KindFloat32,
|
|
|
|
|
objabi.KindFloat64:
|
2016-08-19 22:40:38 -04:00
|
|
|
die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0)
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_float, 0)
|
|
|
|
|
newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.KindComplex64,
|
|
|
|
|
objabi.KindComplex128:
|
2016-08-19 22:40:38 -04:00
|
|
|
die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0)
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_complex_float, 0)
|
|
|
|
|
newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.KindArray:
|
2016-08-19 22:40:38 -04:00
|
|
|
die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_ARRAYTYPE, name, 0)
|
|
|
|
|
dotypedef(ctxt, &dwtypes, name, die)
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
|
2016-08-22 10:33:13 -04:00
|
|
|
s := decodetypeArrayElem(gotype)
|
2016-08-19 22:40:38 -04:00
|
|
|
newrefattr(die, dwarf.DW_AT_type, defgotype(ctxt, s))
|
|
|
|
|
fld := newdie(ctxt, die, dwarf.DW_ABRV_ARRAYRANGE, "range", 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// use actual length not upper bound; correct for 0-length arrays.
|
2016-08-22 10:33:13 -04:00
|
|
|
newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, decodetypeArrayLen(ctxt.Arch, gotype), 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
newrefattr(fld, dwarf.DW_AT_type, mustFind(ctxt, "uintptr"))
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.KindChan:
|
2016-08-19 22:40:38 -04:00
|
|
|
die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_CHANTYPE, name, 0)
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
|
2016-08-22 10:33:13 -04:00
|
|
|
s := decodetypeChanElem(gotype)
|
2016-08-19 22:40:38 -04:00
|
|
|
newrefattr(die, dwarf.DW_AT_go_elem, defgotype(ctxt, s))
|
2016-03-14 09:23:04 -07:00
|
|
|
// Save elem type for synthesizechantypes. We could synthesize here
|
|
|
|
|
// but that would change the order of DIEs we output.
|
2016-07-28 13:04:41 -04:00
|
|
|
newrefattr(die, dwarf.DW_AT_type, s)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.KindFunc:
|
2016-08-19 22:40:38 -04:00
|
|
|
die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_FUNCTYPE, name, 0)
|
2017-08-14 15:07:57 -07:00
|
|
|
newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
|
2016-08-19 22:40:38 -04:00
|
|
|
dotypedef(ctxt, &dwtypes, name, die)
|
|
|
|
|
newrefattr(die, dwarf.DW_AT_type, mustFind(ctxt, "void"))
|
2016-08-22 10:33:13 -04:00
|
|
|
nfields := decodetypeFuncInCount(ctxt.Arch, gotype)
|
2016-07-28 13:04:41 -04:00
|
|
|
var fld *dwarf.DWDie
|
2016-08-19 11:35:54 -04:00
|
|
|
var s *Symbol
|
2015-03-02 12:35:15 -05:00
|
|
|
for i := 0; i < nfields; i++ {
|
2016-08-22 10:33:13 -04:00
|
|
|
s = decodetypeFuncInType(gotype, i)
|
2016-08-19 22:40:38 -04:00
|
|
|
fld = newdie(ctxt, die, dwarf.DW_ABRV_FUNCTYPEPARAM, s.Name[5:], 0)
|
|
|
|
|
newrefattr(fld, dwarf.DW_AT_type, defgotype(ctxt, s))
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-08-22 10:33:13 -04:00
|
|
|
if decodetypeFuncDotdotdot(ctxt.Arch, gotype) {
|
2016-08-19 22:40:38 -04:00
|
|
|
newdie(ctxt, die, dwarf.DW_ABRV_DOTDOTDOT, "...", 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2016-08-22 10:33:13 -04:00
|
|
|
nfields = decodetypeFuncOutCount(ctxt.Arch, gotype)
|
2015-03-02 12:35:15 -05:00
|
|
|
for i := 0; i < nfields; i++ {
|
2016-08-22 10:33:13 -04:00
|
|
|
s = decodetypeFuncOutType(ctxt.Arch, gotype, i)
|
2016-08-19 22:40:38 -04:00
|
|
|
fld = newdie(ctxt, die, dwarf.DW_ABRV_FUNCTYPEPARAM, s.Name[5:], 0)
|
|
|
|
|
newrefattr(fld, dwarf.DW_AT_type, defptrto(ctxt, defgotype(ctxt, s)))
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.KindInterface:
|
2016-08-19 22:40:38 -04:00
|
|
|
die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_IFACETYPE, name, 0)
|
|
|
|
|
dotypedef(ctxt, &dwtypes, name, die)
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
|
2016-08-22 10:33:13 -04:00
|
|
|
nfields := int(decodetypeIfaceMethodCount(ctxt.Arch, gotype))
|
2016-08-19 11:35:54 -04:00
|
|
|
var s *Symbol
|
2015-02-27 22:57:28 -05:00
|
|
|
if nfields == 0 {
|
2016-08-22 10:33:13 -04:00
|
|
|
s = lookupOrDiag(ctxt, "type.runtime.eface")
|
2015-02-27 22:57:28 -05:00
|
|
|
} else {
|
2016-08-22 10:33:13 -04:00
|
|
|
s = lookupOrDiag(ctxt, "type.runtime.iface")
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2016-08-19 22:40:38 -04:00
|
|
|
newrefattr(die, dwarf.DW_AT_type, defgotype(ctxt, s))
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.KindMap:
|
2016-08-19 22:40:38 -04:00
|
|
|
die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_MAPTYPE, name, 0)
|
2016-08-22 10:33:13 -04:00
|
|
|
s := decodetypeMapKey(gotype)
|
2016-08-19 22:40:38 -04:00
|
|
|
newrefattr(die, dwarf.DW_AT_go_key, defgotype(ctxt, s))
|
2016-08-22 10:33:13 -04:00
|
|
|
s = decodetypeMapValue(gotype)
|
2016-08-19 22:40:38 -04:00
|
|
|
newrefattr(die, dwarf.DW_AT_go_elem, defgotype(ctxt, s))
|
2016-03-14 09:23:04 -07:00
|
|
|
// Save gotype for use in synthesizemaptypes. We could synthesize here,
|
|
|
|
|
// but that would change the order of the DIEs.
|
2016-07-28 13:04:41 -04:00
|
|
|
newrefattr(die, dwarf.DW_AT_type, gotype)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.KindPtr:
|
2016-08-19 22:40:38 -04:00
|
|
|
die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_PTRTYPE, name, 0)
|
|
|
|
|
dotypedef(ctxt, &dwtypes, name, die)
|
2016-08-22 10:33:13 -04:00
|
|
|
s := decodetypePtrElem(gotype)
|
2016-08-19 22:40:38 -04:00
|
|
|
newrefattr(die, dwarf.DW_AT_type, defgotype(ctxt, s))
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.KindSlice:
|
2016-08-19 22:40:38 -04:00
|
|
|
die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_SLICETYPE, name, 0)
|
|
|
|
|
dotypedef(ctxt, &dwtypes, name, die)
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
|
2016-08-22 10:33:13 -04:00
|
|
|
s := decodetypeArrayElem(gotype)
|
2016-08-19 22:40:38 -04:00
|
|
|
elem := defgotype(ctxt, s)
|
2016-07-28 13:04:41 -04:00
|
|
|
newrefattr(die, dwarf.DW_AT_go_elem, elem)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.KindString:
|
2016-08-19 22:40:38 -04:00
|
|
|
die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_STRINGTYPE, name, 0)
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.KindStruct:
|
2016-08-19 22:40:38 -04:00
|
|
|
die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_STRUCTTYPE, name, 0)
|
|
|
|
|
dotypedef(ctxt, &dwtypes, name, die)
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
|
2016-08-22 10:33:13 -04:00
|
|
|
nfields := decodetypeStructFieldCount(ctxt.Arch, gotype)
|
2015-03-02 12:35:15 -05:00
|
|
|
for i := 0; i < nfields; i++ {
|
2017-04-26 17:58:31 -04:00
|
|
|
f := decodetypeStructFieldName(gotype, i)
|
|
|
|
|
s := decodetypeStructFieldType(gotype, i)
|
2015-02-27 22:57:28 -05:00
|
|
|
if f == "" {
|
|
|
|
|
f = s.Name[5:] // skip "type."
|
|
|
|
|
}
|
2017-04-26 17:58:31 -04:00
|
|
|
fld := newdie(ctxt, die, dwarf.DW_ABRV_STRUCTFIELD, f, 0)
|
2016-08-19 22:40:38 -04:00
|
|
|
newrefattr(fld, dwarf.DW_AT_type, defgotype(ctxt, s))
|
2017-04-26 17:58:31 -04:00
|
|
|
offsetAnon := decodetypeStructFieldOffsAnon(ctxt.Arch, gotype, i)
|
|
|
|
|
newmemberoffsetattr(fld, int32(offsetAnon>>1))
|
|
|
|
|
if offsetAnon&1 != 0 { // is embedded field
|
|
|
|
|
newattr(fld, dwarf.DW_AT_go_embedded_field, dwarf.DW_CLS_FLAG, 1, 0)
|
|
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.KindUnsafePointer:
|
2016-08-19 22:40:38 -04:00
|
|
|
die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BARE_PTRTYPE, name, 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
default:
|
2016-09-17 09:39:33 -04:00
|
|
|
Errorf(gotype, "dwarf: definition of unknown kind %d", kind)
|
2016-08-19 22:40:38 -04:00
|
|
|
die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_TYPEDECL, name, 0)
|
|
|
|
|
newrefattr(die, dwarf.DW_AT_type, mustFind(ctxt, "<unspecified>"))
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(die, dwarf.DW_AT_go_kind, dwarf.DW_CLS_CONSTANT, int64(kind), 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-03-14 09:23:04 -07:00
|
|
|
if _, ok := prototypedies[gotype.Name]; ok {
|
|
|
|
|
prototypedies[gotype.Name] = die
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-27 22:57:28 -05:00
|
|
|
return die
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-19 11:35:54 -04:00
|
|
|
func nameFromDIESym(dwtype *Symbol) string {
|
2016-07-28 13:04:41 -04:00
|
|
|
return strings.TrimSuffix(dwtype.Name[len(dwarf.InfoPrefix):], "..def")
|
2016-03-14 09:23:04 -07:00
|
|
|
}
|
|
|
|
|
|
2015-02-27 22:57:28 -05:00
|
|
|
// Find or construct *T given T.
|
2016-08-19 22:40:38 -04:00
|
|
|
func defptrto(ctxt *Link, dwtype *Symbol) *Symbol {
|
2016-03-14 09:23:04 -07:00
|
|
|
ptrname := "*" + nameFromDIESym(dwtype)
|
2016-08-19 22:40:38 -04:00
|
|
|
die := find(ctxt, ptrname)
|
2015-02-27 22:57:28 -05:00
|
|
|
if die == nil {
|
2016-08-19 22:40:38 -04:00
|
|
|
pdie := newdie(ctxt, &dwtypes, dwarf.DW_ABRV_PTRTYPE, ptrname, 0)
|
2016-07-28 13:04:41 -04:00
|
|
|
newrefattr(pdie, dwarf.DW_AT_type, dwtype)
|
|
|
|
|
return dtolsym(pdie.Sym)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return die
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Copies src's children into dst. Copies attributes by value.
|
2016-03-01 23:21:55 +00:00
|
|
|
// DWAttr.data is copied as pointer only. If except is one of
|
2015-02-27 22:57:28 -05:00
|
|
|
// the top-level children, it will not be copied.
|
2016-08-19 22:40:38 -04:00
|
|
|
func copychildrenexcept(ctxt *Link, dst *dwarf.DWDie, src *dwarf.DWDie, except *dwarf.DWDie) {
|
2016-07-28 13:04:41 -04:00
|
|
|
for src = src.Child; src != nil; src = src.Link {
|
2015-02-27 22:57:28 -05:00
|
|
|
if src == except {
|
|
|
|
|
continue
|
|
|
|
|
}
|
2016-08-19 22:40:38 -04:00
|
|
|
c := newdie(ctxt, dst, src.Abbrev, getattr(src, dwarf.DW_AT_name).Data.(string), 0)
|
2016-07-28 13:04:41 -04:00
|
|
|
for a := src.Attr; a != nil; a = a.Link {
|
|
|
|
|
newattr(c, a.Atr, int(a.Cls), a.Value, a.Data)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2016-08-19 22:40:38 -04:00
|
|
|
copychildrenexcept(ctxt, c, src, nil)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
reverselist(&dst.Child)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
func copychildren(ctxt *Link, dst *dwarf.DWDie, src *dwarf.DWDie) {
|
|
|
|
|
copychildrenexcept(ctxt, dst, src, nil)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
// Search children (assumed to have TAG_member) for the one named
|
|
|
|
|
// field and set its AT_type to dwtype
|
2016-08-19 11:35:54 -04:00
|
|
|
func substitutetype(structdie *dwarf.DWDie, field string, dwtype *Symbol) {
|
2016-03-14 09:23:04 -07:00
|
|
|
child := findchild(structdie, field)
|
2015-02-27 22:57:28 -05:00
|
|
|
if child == nil {
|
2016-03-14 09:23:04 -07:00
|
|
|
Exitf("dwarf substitutetype: %s does not have member %s",
|
2016-07-28 13:04:41 -04:00
|
|
|
getattr(structdie, dwarf.DW_AT_name).Data, field)
|
2015-02-27 22:57:28 -05:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
a := getattr(child, dwarf.DW_AT_type)
|
2015-02-27 22:57:28 -05:00
|
|
|
if a != nil {
|
2016-07-28 13:04:41 -04:00
|
|
|
a.Data = dwtype
|
2015-02-27 22:57:28 -05:00
|
|
|
} else {
|
2016-07-28 13:04:41 -04:00
|
|
|
newrefattr(child, dwarf.DW_AT_type, dwtype)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
func findprotodie(ctxt *Link, name string) *dwarf.DWDie {
|
2016-03-14 09:23:04 -07:00
|
|
|
die, ok := prototypedies[name]
|
|
|
|
|
if ok && die == nil {
|
2016-08-22 10:33:13 -04:00
|
|
|
defgotype(ctxt, lookupOrDiag(ctxt, name))
|
2016-03-14 09:23:04 -07:00
|
|
|
die = prototypedies[name]
|
|
|
|
|
}
|
|
|
|
|
return die
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
func synthesizestringtypes(ctxt *Link, die *dwarf.DWDie) {
|
|
|
|
|
prototype := walktypedef(findprotodie(ctxt, "type.runtime.stringStructDWARF"))
|
2015-02-27 22:57:28 -05:00
|
|
|
if prototype == nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
for ; die != nil; die = die.Link {
|
|
|
|
|
if die.Abbrev != dwarf.DW_ABRV_STRINGTYPE {
|
2015-02-27 22:57:28 -05:00
|
|
|
continue
|
|
|
|
|
}
|
2016-08-19 22:40:38 -04:00
|
|
|
copychildren(ctxt, die, prototype)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
func synthesizeslicetypes(ctxt *Link, die *dwarf.DWDie) {
|
|
|
|
|
prototype := walktypedef(findprotodie(ctxt, "type.runtime.slice"))
|
2015-02-27 22:57:28 -05:00
|
|
|
if prototype == nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
for ; die != nil; die = die.Link {
|
|
|
|
|
if die.Abbrev != dwarf.DW_ABRV_SLICETYPE {
|
2015-02-27 22:57:28 -05:00
|
|
|
continue
|
|
|
|
|
}
|
2016-08-19 22:40:38 -04:00
|
|
|
copychildren(ctxt, die, prototype)
|
2016-08-19 11:35:54 -04:00
|
|
|
elem := getattr(die, dwarf.DW_AT_go_elem).Data.(*Symbol)
|
2016-08-19 22:40:38 -04:00
|
|
|
substitutetype(die, "array", defptrto(ctxt, elem))
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func mkinternaltypename(base string, arg1 string, arg2 string) string {
|
|
|
|
|
var buf string
|
|
|
|
|
|
|
|
|
|
if arg2 == "" {
|
|
|
|
|
buf = fmt.Sprintf("%s<%s>", base, arg1)
|
|
|
|
|
} else {
|
|
|
|
|
buf = fmt.Sprintf("%s<%s,%s>", base, arg1, arg2)
|
|
|
|
|
}
|
2015-03-02 12:35:15 -05:00
|
|
|
n := buf
|
2015-02-27 22:57:28 -05:00
|
|
|
return n
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// synthesizemaptypes is way too closely married to runtime/hashmap.c
|
|
|
|
|
const (
|
|
|
|
|
MaxKeySize = 128
|
|
|
|
|
MaxValSize = 128
|
|
|
|
|
BucketSize = 8
|
|
|
|
|
)
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
func mkinternaltype(ctxt *Link, abbrev int, typename, keyname, valname string, f func(*dwarf.DWDie)) *Symbol {
|
2016-03-14 09:23:04 -07:00
|
|
|
name := mkinternaltypename(typename, keyname, valname)
|
2016-07-28 13:04:41 -04:00
|
|
|
symname := dwarf.InfoPrefix + name
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
s := ctxt.Syms.ROLookup(symname, 0)
|
2017-04-19 15:15:35 +12:00
|
|
|
if s != nil && s.Type == SDWARFINFO {
|
2016-03-14 09:23:04 -07:00
|
|
|
return s
|
|
|
|
|
}
|
2016-08-19 22:40:38 -04:00
|
|
|
die := newdie(ctxt, &dwtypes, abbrev, name, 0)
|
2016-03-14 09:23:04 -07:00
|
|
|
f(die)
|
2016-07-28 13:04:41 -04:00
|
|
|
return dtolsym(die.Sym)
|
2016-03-14 09:23:04 -07:00
|
|
|
}
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
func synthesizemaptypes(ctxt *Link, die *dwarf.DWDie) {
|
|
|
|
|
hash := walktypedef(findprotodie(ctxt, "type.runtime.hmap"))
|
|
|
|
|
bucket := walktypedef(findprotodie(ctxt, "type.runtime.bmap"))
|
2015-03-02 12:35:15 -05:00
|
|
|
|
|
|
|
|
if hash == nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
for ; die != nil; die = die.Link {
|
|
|
|
|
if die.Abbrev != dwarf.DW_ABRV_MAPTYPE {
|
2015-02-27 22:57:28 -05:00
|
|
|
continue
|
|
|
|
|
}
|
2016-08-19 11:35:54 -04:00
|
|
|
gotype := getattr(die, dwarf.DW_AT_type).Data.(*Symbol)
|
2016-08-22 10:33:13 -04:00
|
|
|
keytype := decodetypeMapKey(gotype)
|
|
|
|
|
valtype := decodetypeMapValue(gotype)
|
|
|
|
|
keysize, valsize := decodetypeSize(ctxt.Arch, keytype), decodetypeSize(ctxt.Arch, valtype)
|
2016-08-19 22:40:38 -04:00
|
|
|
keytype, valtype = walksymtypedef(ctxt, defgotype(ctxt, keytype)), walksymtypedef(ctxt, defgotype(ctxt, valtype))
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// compute size info like hashmap.c does.
|
2016-08-22 10:33:13 -04:00
|
|
|
indirectKey, indirectVal := false, false
|
2015-02-27 22:57:28 -05:00
|
|
|
if keysize > MaxKeySize {
|
2016-04-06 12:01:40 -07:00
|
|
|
keysize = int64(SysArch.PtrSize)
|
2016-08-22 10:33:13 -04:00
|
|
|
indirectKey = true
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
if valsize > MaxValSize {
|
2016-04-06 12:01:40 -07:00
|
|
|
valsize = int64(SysArch.PtrSize)
|
2016-08-22 10:33:13 -04:00
|
|
|
indirectVal = true
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Construct type to represent an array of BucketSize keys
|
2016-03-14 09:23:04 -07:00
|
|
|
keyname := nameFromDIESym(keytype)
|
2016-08-19 22:40:38 -04:00
|
|
|
dwhks := mkinternaltype(ctxt, dwarf.DW_ABRV_ARRAYTYPE, "[]key", keyname, "", func(dwhk *dwarf.DWDie) {
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(dwhk, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, BucketSize*keysize, 0)
|
2016-03-14 09:23:04 -07:00
|
|
|
t := keytype
|
2016-08-22 10:33:13 -04:00
|
|
|
if indirectKey {
|
2016-08-19 22:40:38 -04:00
|
|
|
t = defptrto(ctxt, keytype)
|
2016-03-14 09:23:04 -07:00
|
|
|
}
|
2016-07-28 13:04:41 -04:00
|
|
|
newrefattr(dwhk, dwarf.DW_AT_type, t)
|
2016-08-19 22:40:38 -04:00
|
|
|
fld := newdie(ctxt, dwhk, dwarf.DW_ABRV_ARRAYRANGE, "size", 0)
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, BucketSize, 0)
|
2016-08-19 22:40:38 -04:00
|
|
|
newrefattr(fld, dwarf.DW_AT_type, mustFind(ctxt, "uintptr"))
|
2016-03-14 09:23:04 -07:00
|
|
|
})
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// Construct type to represent an array of BucketSize values
|
2016-03-14 09:23:04 -07:00
|
|
|
valname := nameFromDIESym(valtype)
|
2016-08-19 22:40:38 -04:00
|
|
|
dwhvs := mkinternaltype(ctxt, dwarf.DW_ABRV_ARRAYTYPE, "[]val", valname, "", func(dwhv *dwarf.DWDie) {
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(dwhv, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, BucketSize*valsize, 0)
|
2016-03-14 09:23:04 -07:00
|
|
|
t := valtype
|
2016-08-22 10:33:13 -04:00
|
|
|
if indirectVal {
|
2016-08-19 22:40:38 -04:00
|
|
|
t = defptrto(ctxt, valtype)
|
2016-03-14 09:23:04 -07:00
|
|
|
}
|
2016-07-28 13:04:41 -04:00
|
|
|
newrefattr(dwhv, dwarf.DW_AT_type, t)
|
2016-08-19 22:40:38 -04:00
|
|
|
fld := newdie(ctxt, dwhv, dwarf.DW_ABRV_ARRAYRANGE, "size", 0)
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, BucketSize, 0)
|
2016-08-19 22:40:38 -04:00
|
|
|
newrefattr(fld, dwarf.DW_AT_type, mustFind(ctxt, "uintptr"))
|
2016-03-14 09:23:04 -07:00
|
|
|
})
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// Construct bucket<K,V>
|
2016-08-19 22:40:38 -04:00
|
|
|
dwhbs := mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "bucket", keyname, valname, func(dwhb *dwarf.DWDie) {
|
2016-03-14 09:23:04 -07:00
|
|
|
// Copy over all fields except the field "data" from the generic
|
|
|
|
|
// bucket. "data" will be replaced with keys/values below.
|
2016-08-19 22:40:38 -04:00
|
|
|
copychildrenexcept(ctxt, dwhb, bucket, findchild(bucket, "data"))
|
2016-03-14 09:23:04 -07:00
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
fld := newdie(ctxt, dwhb, dwarf.DW_ABRV_STRUCTFIELD, "keys", 0)
|
2016-07-28 13:04:41 -04:00
|
|
|
newrefattr(fld, dwarf.DW_AT_type, dwhks)
|
2016-03-14 09:23:04 -07:00
|
|
|
newmemberoffsetattr(fld, BucketSize)
|
2016-08-19 22:40:38 -04:00
|
|
|
fld = newdie(ctxt, dwhb, dwarf.DW_ABRV_STRUCTFIELD, "values", 0)
|
2016-07-28 13:04:41 -04:00
|
|
|
newrefattr(fld, dwarf.DW_AT_type, dwhvs)
|
2016-03-14 09:23:04 -07:00
|
|
|
newmemberoffsetattr(fld, BucketSize+BucketSize*int32(keysize))
|
2016-08-19 22:40:38 -04:00
|
|
|
fld = newdie(ctxt, dwhb, dwarf.DW_ABRV_STRUCTFIELD, "overflow", 0)
|
|
|
|
|
newrefattr(fld, dwarf.DW_AT_type, defptrto(ctxt, dtolsym(dwhb.Sym)))
|
2016-03-14 09:23:04 -07:00
|
|
|
newmemberoffsetattr(fld, BucketSize+BucketSize*(int32(keysize)+int32(valsize)))
|
2016-04-06 12:01:40 -07:00
|
|
|
if SysArch.RegSize > SysArch.PtrSize {
|
2016-08-19 22:40:38 -04:00
|
|
|
fld = newdie(ctxt, dwhb, dwarf.DW_ABRV_STRUCTFIELD, "pad", 0)
|
|
|
|
|
newrefattr(fld, dwarf.DW_AT_type, mustFind(ctxt, "uintptr"))
|
2016-04-06 12:01:40 -07:00
|
|
|
newmemberoffsetattr(fld, BucketSize+BucketSize*(int32(keysize)+int32(valsize))+int32(SysArch.PtrSize))
|
2016-03-14 09:23:04 -07:00
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(dwhb, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, BucketSize+BucketSize*keysize+BucketSize*valsize+int64(SysArch.RegSize), 0)
|
2016-03-14 09:23:04 -07:00
|
|
|
})
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// Construct hash<K,V>
|
2016-08-19 22:40:38 -04:00
|
|
|
dwhs := mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "hash", keyname, valname, func(dwh *dwarf.DWDie) {
|
|
|
|
|
copychildren(ctxt, dwh, hash)
|
|
|
|
|
substitutetype(dwh, "buckets", defptrto(ctxt, dwhbs))
|
|
|
|
|
substitutetype(dwh, "oldbuckets", defptrto(ctxt, dwhbs))
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(dwh, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, getattr(hash, dwarf.DW_AT_byte_size).Value, nil)
|
2016-03-14 09:23:04 -07:00
|
|
|
})
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// make map type a pointer to hash<K,V>
|
2016-08-19 22:40:38 -04:00
|
|
|
newrefattr(die, dwarf.DW_AT_type, defptrto(ctxt, dwhs))
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
func synthesizechantypes(ctxt *Link, die *dwarf.DWDie) {
|
|
|
|
|
sudog := walktypedef(findprotodie(ctxt, "type.runtime.sudog"))
|
|
|
|
|
waitq := walktypedef(findprotodie(ctxt, "type.runtime.waitq"))
|
|
|
|
|
hchan := walktypedef(findprotodie(ctxt, "type.runtime.hchan"))
|
2015-02-27 22:57:28 -05:00
|
|
|
if sudog == nil || waitq == nil || hchan == nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
sudogsize := int(getattr(sudog, dwarf.DW_AT_byte_size).Value)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
for ; die != nil; die = die.Link {
|
|
|
|
|
if die.Abbrev != dwarf.DW_ABRV_CHANTYPE {
|
2015-02-27 22:57:28 -05:00
|
|
|
continue
|
|
|
|
|
}
|
2016-08-19 11:35:54 -04:00
|
|
|
elemgotype := getattr(die, dwarf.DW_AT_type).Data.(*Symbol)
|
2016-03-14 09:23:04 -07:00
|
|
|
elemname := elemgotype.Name[5:]
|
2016-08-19 22:40:38 -04:00
|
|
|
elemtype := walksymtypedef(ctxt, defgotype(ctxt, elemgotype))
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// sudog<T>
|
2016-08-19 22:40:38 -04:00
|
|
|
dwss := mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "sudog", elemname, "", func(dws *dwarf.DWDie) {
|
|
|
|
|
copychildren(ctxt, dws, sudog)
|
2017-07-19 19:52:29 -07:00
|
|
|
substitutetype(dws, "elem", defptrto(ctxt, elemtype))
|
|
|
|
|
newattr(dws, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, int64(sudogsize), nil)
|
2016-03-14 09:23:04 -07:00
|
|
|
})
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// waitq<T>
|
2016-08-19 22:40:38 -04:00
|
|
|
dwws := mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "waitq", elemname, "", func(dww *dwarf.DWDie) {
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
copychildren(ctxt, dww, waitq)
|
|
|
|
|
substitutetype(dww, "first", defptrto(ctxt, dwss))
|
|
|
|
|
substitutetype(dww, "last", defptrto(ctxt, dwss))
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(dww, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, getattr(waitq, dwarf.DW_AT_byte_size).Value, nil)
|
2016-03-14 09:23:04 -07:00
|
|
|
})
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// hchan<T>
|
2016-08-19 22:40:38 -04:00
|
|
|
dwhs := mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "hchan", elemname, "", func(dwh *dwarf.DWDie) {
|
|
|
|
|
copychildren(ctxt, dwh, hchan)
|
2016-03-14 09:23:04 -07:00
|
|
|
substitutetype(dwh, "recvq", dwws)
|
|
|
|
|
substitutetype(dwh, "sendq", dwws)
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(dwh, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, getattr(hchan, dwarf.DW_AT_byte_size).Value, nil)
|
2016-03-14 09:23:04 -07:00
|
|
|
})
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
newrefattr(die, dwarf.DW_AT_type, defptrto(ctxt, dwhs))
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// For use with pass.c::genasmsym
|
2016-09-16 16:47:28 +12:00
|
|
|
func defdwsymb(ctxt *Link, sym *Symbol, s string, t SymbolType, v int64, gotype *Symbol) {
|
2015-02-27 22:57:28 -05:00
|
|
|
if strings.HasPrefix(s, "go.string.") {
|
|
|
|
|
return
|
|
|
|
|
}
|
2015-07-22 14:59:56 -04:00
|
|
|
if strings.HasPrefix(s, "runtime.gcbits.") {
|
|
|
|
|
return
|
|
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
if strings.HasPrefix(s, "type.") && s != "type.*" && !strings.HasPrefix(s, "type..") {
|
2016-08-19 22:40:38 -04:00
|
|
|
defgotype(ctxt, sym)
|
2015-02-27 22:57:28 -05:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
var dv *dwarf.DWDie
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-08-19 11:35:54 -04:00
|
|
|
var dt *Symbol
|
2015-02-27 22:57:28 -05:00
|
|
|
switch t {
|
|
|
|
|
default:
|
|
|
|
|
return
|
|
|
|
|
|
2016-09-16 16:22:08 +12:00
|
|
|
case DataSym, BSSSym:
|
2016-09-16 16:47:28 +12:00
|
|
|
dv = newdie(ctxt, &dwglobals, dwarf.DW_ABRV_VARIABLE, s, int(sym.Version))
|
2015-02-27 22:57:28 -05:00
|
|
|
newabslocexprattr(dv, v, sym)
|
2016-09-16 16:47:28 +12:00
|
|
|
if sym.Version == 0 {
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(dv, dwarf.DW_AT_external, dwarf.DW_CLS_FLAG, 1, 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
fallthrough
|
|
|
|
|
|
2016-09-16 16:22:08 +12:00
|
|
|
case AutoSym, ParamSym:
|
2016-08-19 22:40:38 -04:00
|
|
|
dt = defgotype(ctxt, gotype)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if dv != nil {
|
2016-07-28 13:04:41 -04:00
|
|
|
newrefattr(dv, dwarf.DW_AT_type, dt)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
func movetomodule(parent *dwarf.DWDie) {
|
|
|
|
|
die := dwroot.Child.Child
|
|
|
|
|
if die == nil {
|
|
|
|
|
dwroot.Child.Child = parent.Child
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
for die.Link != nil {
|
|
|
|
|
die = die.Link
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2016-07-28 13:04:41 -04:00
|
|
|
die.Link = parent.Child
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If the pcln table contains runtime/runtime.go, use that to set gdbscript path.
|
2016-08-19 11:35:54 -04:00
|
|
|
func finddebugruntimepath(s *Symbol) {
|
2015-02-27 22:57:28 -05:00
|
|
|
if gdbscript != "" {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-12 23:18:47 +03:00
|
|
|
for i := range s.FuncInfo.File {
|
|
|
|
|
f := s.FuncInfo.File[i]
|
2017-05-11 11:55:59 +10:00
|
|
|
if i := strings.Index(f.Name, "runtime/debug.go"); i >= 0 {
|
2015-02-27 22:57:28 -05:00
|
|
|
gdbscript = f.Name[:i] + "runtime/runtime-gdb.py"
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2016-10-07 15:06:09 +11:00
|
|
|
* Generate a sequence of opcodes that is as short as possible.
|
2015-02-27 22:57:28 -05:00
|
|
|
* See section 6.2.5
|
|
|
|
|
*/
|
|
|
|
|
const (
|
2016-10-07 15:06:09 +11:00
|
|
|
LINE_BASE = -4
|
|
|
|
|
LINE_RANGE = 10
|
|
|
|
|
PC_RANGE = (255 - OPCODE_BASE) / LINE_RANGE
|
2015-02-27 22:57:28 -05:00
|
|
|
OPCODE_BASE = 10
|
|
|
|
|
)
|
|
|
|
|
|
2016-10-07 15:06:09 +11:00
|
|
|
func putpclcdelta(linkctxt *Link, ctxt dwarf.Context, s *Symbol, deltaPC uint64, deltaLC int64) {
|
|
|
|
|
// Choose a special opcode that minimizes the number of bytes needed to
|
|
|
|
|
// encode the remaining PC delta and LC delta.
|
|
|
|
|
var opcode int64
|
|
|
|
|
if deltaLC < LINE_BASE {
|
|
|
|
|
if deltaPC >= PC_RANGE {
|
|
|
|
|
opcode = OPCODE_BASE + (LINE_RANGE * PC_RANGE)
|
|
|
|
|
} else {
|
|
|
|
|
opcode = OPCODE_BASE + (LINE_RANGE * int64(deltaPC))
|
|
|
|
|
}
|
|
|
|
|
} else if deltaLC < LINE_BASE+LINE_RANGE {
|
|
|
|
|
if deltaPC >= PC_RANGE {
|
|
|
|
|
opcode = OPCODE_BASE + (deltaLC - LINE_BASE) + (LINE_RANGE * PC_RANGE)
|
|
|
|
|
if opcode > 255 {
|
|
|
|
|
opcode -= LINE_RANGE
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
opcode = OPCODE_BASE + (deltaLC - LINE_BASE) + (LINE_RANGE * int64(deltaPC))
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if deltaPC <= PC_RANGE {
|
|
|
|
|
opcode = OPCODE_BASE + (LINE_RANGE - 1) + (LINE_RANGE * int64(deltaPC))
|
|
|
|
|
if opcode > 255 {
|
|
|
|
|
opcode = 255
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Use opcode 249 (pc+=23, lc+=5) or 255 (pc+=24, lc+=1).
|
|
|
|
|
//
|
|
|
|
|
// Let x=deltaPC-PC_RANGE. If we use opcode 255, x will be the remaining
|
|
|
|
|
// deltaPC that we need to encode separately before emitting 255. If we
|
|
|
|
|
// use opcode 249, we will need to encode x+1. If x+1 takes one more
|
|
|
|
|
// byte to encode than x, then we use opcode 255.
|
|
|
|
|
//
|
|
|
|
|
// In all other cases x and x+1 take the same number of bytes to encode,
|
|
|
|
|
// so we use opcode 249, which may save us a byte in encoding deltaLC,
|
|
|
|
|
// for similar reasons.
|
|
|
|
|
switch deltaPC - PC_RANGE {
|
|
|
|
|
// PC_RANGE is the largest deltaPC we can encode in one byte, using
|
|
|
|
|
// DW_LNS_const_add_pc.
|
|
|
|
|
//
|
|
|
|
|
// (1<<16)-1 is the largest deltaPC we can encode in three bytes, using
|
|
|
|
|
// DW_LNS_fixed_advance_pc.
|
|
|
|
|
//
|
|
|
|
|
// (1<<(7n))-1 is the largest deltaPC we can encode in n+1 bytes for
|
|
|
|
|
// n=1,3,4,5,..., using DW_LNS_advance_pc.
|
|
|
|
|
case PC_RANGE, (1 << 7) - 1, (1 << 16) - 1, (1 << 21) - 1, (1 << 28) - 1,
|
|
|
|
|
(1 << 35) - 1, (1 << 42) - 1, (1 << 49) - 1, (1 << 56) - 1, (1 << 63) - 1:
|
|
|
|
|
opcode = 255
|
|
|
|
|
default:
|
|
|
|
|
opcode = OPCODE_BASE + LINE_RANGE*PC_RANGE - 1 // 249
|
|
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
2016-10-07 15:06:09 +11:00
|
|
|
if opcode < OPCODE_BASE || opcode > 255 {
|
|
|
|
|
panic(fmt.Sprintf("produced invalid special opcode %d", opcode))
|
|
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-10-07 15:06:09 +11:00
|
|
|
// Subtract from deltaPC and deltaLC the amounts that the opcode will add.
|
|
|
|
|
deltaPC -= uint64((opcode - OPCODE_BASE) / LINE_RANGE)
|
|
|
|
|
deltaLC -= int64((opcode-OPCODE_BASE)%LINE_RANGE + LINE_BASE)
|
|
|
|
|
|
|
|
|
|
// Encode deltaPC.
|
2016-08-22 10:33:13 -04:00
|
|
|
if deltaPC != 0 {
|
2016-10-07 15:06:09 +11:00
|
|
|
if deltaPC <= PC_RANGE {
|
|
|
|
|
// Adjust the opcode so that we can use the 1-byte DW_LNS_const_add_pc
|
|
|
|
|
// instruction.
|
|
|
|
|
opcode -= LINE_RANGE * int64(PC_RANGE-deltaPC)
|
|
|
|
|
if opcode < OPCODE_BASE {
|
|
|
|
|
panic(fmt.Sprintf("produced invalid special opcode %d", opcode))
|
|
|
|
|
}
|
|
|
|
|
Adduint8(linkctxt, s, dwarf.DW_LNS_const_add_pc)
|
|
|
|
|
} else if (1<<14) <= deltaPC && deltaPC < (1<<16) {
|
|
|
|
|
Adduint8(linkctxt, s, dwarf.DW_LNS_fixed_advance_pc)
|
|
|
|
|
Adduint16(linkctxt, s, uint16(deltaPC))
|
|
|
|
|
} else {
|
|
|
|
|
Adduint8(linkctxt, s, dwarf.DW_LNS_advance_pc)
|
|
|
|
|
dwarf.Uleb128put(ctxt, s, int64(deltaPC))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Encode deltaLC.
|
|
|
|
|
if deltaLC != 0 {
|
|
|
|
|
Adduint8(linkctxt, s, dwarf.DW_LNS_advance_line)
|
|
|
|
|
dwarf.Sleb128put(ctxt, s, deltaLC)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-10-07 15:06:09 +11:00
|
|
|
// Output the special opcode.
|
|
|
|
|
Adduint8(linkctxt, s, uint8(opcode))
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Walk prog table, emit line program and build DIE tree.
|
|
|
|
|
*/
|
|
|
|
|
|
2015-04-08 12:55:34 -07:00
|
|
|
func getCompilationDir() string {
|
|
|
|
|
if dir, err := os.Getwd(); err == nil {
|
|
|
|
|
return dir
|
|
|
|
|
}
|
|
|
|
|
return "/"
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
func writelines(ctxt *Link, syms []*Symbol) ([]*Symbol, []*Symbol) {
|
|
|
|
|
var dwarfctxt dwarf.Context = dwctxt{ctxt}
|
2017-05-22 20:17:31 -04:00
|
|
|
ls := ctxt.Syms.Lookup(".debug_line", 0)
|
|
|
|
|
ls.Type = SDWARFSECT
|
|
|
|
|
ls.R = ls.R[:0]
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
syms = append(syms, ls)
|
2016-08-19 11:35:54 -04:00
|
|
|
var funcs []*Symbol
|
2016-03-14 09:23:04 -07:00
|
|
|
|
2015-03-02 12:35:15 -05:00
|
|
|
unitstart := int64(-1)
|
2016-03-14 09:23:04 -07:00
|
|
|
headerstart := int64(-1)
|
2015-03-02 12:35:15 -05:00
|
|
|
headerend := int64(-1)
|
|
|
|
|
epc := int64(0)
|
2016-08-19 11:35:54 -04:00
|
|
|
var epcs *Symbol
|
2016-07-28 13:04:41 -04:00
|
|
|
var dwinfo *dwarf.DWDie
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
lang := dwarf.DW_LANG_Go
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
s := ctxt.Textp[0]
|
2017-04-18 12:53:25 -07:00
|
|
|
if ctxt.DynlinkingGo() && Headtype == objabi.Hdarwin {
|
2016-09-19 14:13:07 -04:00
|
|
|
s = ctxt.Textp[1] // skip runtime.text
|
|
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
dwinfo = newdie(ctxt, &dwroot, dwarf.DW_ABRV_COMPUNIT, "go", 0)
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(dwinfo, dwarf.DW_AT_language, dwarf.DW_CLS_CONSTANT, int64(lang), 0)
|
2017-05-22 20:17:31 -04:00
|
|
|
newattr(dwinfo, dwarf.DW_AT_stmt_list, dwarf.DW_CLS_PTR, 0, ls)
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(dwinfo, dwarf.DW_AT_low_pc, dwarf.DW_CLS_ADDRESS, s.Value, s)
|
2015-04-08 12:55:34 -07:00
|
|
|
// OS X linker requires compilation dir or absolute path in comp unit name to output debug info.
|
|
|
|
|
compDir := getCompilationDir()
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(dwinfo, dwarf.DW_AT_comp_dir, dwarf.DW_CLS_STRING, int64(len(compDir)), compDir)
|
2017-05-08 14:37:02 -04:00
|
|
|
producer := "Go cmd/compile " + objabi.Version
|
|
|
|
|
newattr(dwinfo, dwarf.DW_AT_producer, dwarf.DW_CLS_STRING, int64(len(producer)), producer)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// Write .debug_line Line Number Program Header (sec 6.2.4)
|
|
|
|
|
// Fields marked with (*) must be changed for 64-bit dwarf
|
2016-08-22 10:33:13 -04:00
|
|
|
unitLengthOffset := ls.Size
|
2016-08-19 22:40:38 -04:00
|
|
|
Adduint32(ctxt, ls, 0) // unit_length (*), filled in at end.
|
2016-03-14 09:23:04 -07:00
|
|
|
unitstart = ls.Size
|
2016-08-19 22:40:38 -04:00
|
|
|
Adduint16(ctxt, ls, 2) // dwarf version (appendix F)
|
2016-08-22 10:33:13 -04:00
|
|
|
headerLengthOffset := ls.Size
|
2016-08-19 22:40:38 -04:00
|
|
|
Adduint32(ctxt, ls, 0) // header_length (*), filled in at end.
|
2016-03-14 09:23:04 -07:00
|
|
|
headerstart = ls.Size
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// cpos == unitstart + 4 + 2 + 4
|
2016-08-19 22:40:38 -04:00
|
|
|
Adduint8(ctxt, ls, 1) // minimum_instruction_length
|
|
|
|
|
Adduint8(ctxt, ls, 1) // default_is_stmt
|
|
|
|
|
Adduint8(ctxt, ls, LINE_BASE&0xFF) // line_base
|
|
|
|
|
Adduint8(ctxt, ls, LINE_RANGE) // line_range
|
|
|
|
|
Adduint8(ctxt, ls, OPCODE_BASE) // opcode_base
|
|
|
|
|
Adduint8(ctxt, ls, 0) // standard_opcode_lengths[1]
|
|
|
|
|
Adduint8(ctxt, ls, 1) // standard_opcode_lengths[2]
|
|
|
|
|
Adduint8(ctxt, ls, 1) // standard_opcode_lengths[3]
|
|
|
|
|
Adduint8(ctxt, ls, 1) // standard_opcode_lengths[4]
|
|
|
|
|
Adduint8(ctxt, ls, 1) // standard_opcode_lengths[5]
|
|
|
|
|
Adduint8(ctxt, ls, 0) // standard_opcode_lengths[6]
|
|
|
|
|
Adduint8(ctxt, ls, 0) // standard_opcode_lengths[7]
|
|
|
|
|
Adduint8(ctxt, ls, 0) // standard_opcode_lengths[8]
|
|
|
|
|
Adduint8(ctxt, ls, 1) // standard_opcode_lengths[9]
|
|
|
|
|
Adduint8(ctxt, ls, 0) // include_directories (empty)
|
|
|
|
|
|
|
|
|
|
for _, f := range ctxt.Filesyms {
|
2016-09-20 15:31:26 +12:00
|
|
|
Addstring(ls, f.Name)
|
2016-08-19 22:40:38 -04:00
|
|
|
Adduint8(ctxt, ls, 0)
|
|
|
|
|
Adduint8(ctxt, ls, 0)
|
|
|
|
|
Adduint8(ctxt, ls, 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 4 zeros: the string termination + 3 fields.
|
2016-08-19 22:40:38 -04:00
|
|
|
Adduint8(ctxt, ls, 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
// terminate file_names.
|
2016-03-14 09:23:04 -07:00
|
|
|
headerend = ls.Size
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
Adduint8(ctxt, ls, 0) // start extended opcode
|
2016-07-28 13:04:41 -04:00
|
|
|
dwarf.Uleb128put(dwarfctxt, ls, 1+int64(SysArch.PtrSize))
|
2016-08-19 22:40:38 -04:00
|
|
|
Adduint8(ctxt, ls, dwarf.DW_LNE_set_address)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2015-03-02 12:35:15 -05:00
|
|
|
pc := s.Value
|
|
|
|
|
line := 1
|
|
|
|
|
file := 1
|
2016-08-19 22:40:38 -04:00
|
|
|
Addaddr(ctxt, ls, s)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2015-03-02 12:35:15 -05:00
|
|
|
var pcfile Pciter
|
|
|
|
|
var pcline Pciter
|
2016-09-17 10:01:17 -04:00
|
|
|
for _, s := range ctxt.Textp {
|
2017-08-24 14:29:13 -04:00
|
|
|
if s.FuncInfo == nil {
|
|
|
|
|
continue
|
|
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
epc = s.Value + s.Size
|
|
|
|
|
epcs = s
|
2016-07-28 13:04:41 -04:00
|
|
|
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
dsym := ctxt.Syms.Lookup(dwarf.InfoPrefix+s.Name, int(s.Version))
|
2017-04-28 12:22:50 +12:00
|
|
|
dsym.Attr |= AttrNotInSymbolTable | AttrReachable
|
2017-04-19 15:15:35 +12:00
|
|
|
dsym.Type = SDWARFINFO
|
2016-07-28 13:04:41 -04:00
|
|
|
for _, r := range dsym.R {
|
2017-04-18 12:53:25 -07:00
|
|
|
if r.Type == objabi.R_DWARFREF && r.Sym.Size == 0 {
|
2016-07-28 13:04:41 -04:00
|
|
|
if Buildmode == BuildmodeShared {
|
|
|
|
|
// These type symbols may not be present in BuildmodeShared. Skip.
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
n := nameFromDIESym(r.Sym)
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
defgotype(ctxt, ctxt.Syms.Lookup("type."+n, 0))
|
2016-07-28 13:04:41 -04:00
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2016-07-28 13:04:41 -04:00
|
|
|
funcs = append(funcs, dsym)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
finddebugruntimepath(s)
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
pciterinit(ctxt, &pcfile, &s.FuncInfo.Pcfile)
|
|
|
|
|
pciterinit(ctxt, &pcline, &s.FuncInfo.Pcline)
|
2015-02-27 22:57:28 -05:00
|
|
|
epc = pc
|
|
|
|
|
for pcfile.done == 0 && pcline.done == 0 {
|
|
|
|
|
if epc-s.Value >= int64(pcfile.nextpc) {
|
|
|
|
|
pciternext(&pcfile)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if epc-s.Value >= int64(pcline.nextpc) {
|
|
|
|
|
pciternext(&pcline)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if int32(file) != pcfile.value {
|
2016-08-19 22:40:38 -04:00
|
|
|
Adduint8(ctxt, ls, dwarf.DW_LNS_set_file)
|
2016-07-28 13:04:41 -04:00
|
|
|
dwarf.Uleb128put(dwarfctxt, ls, int64(pcfile.value))
|
2015-02-27 22:57:28 -05:00
|
|
|
file = int(pcfile.value)
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-07 15:06:09 +11:00
|
|
|
putpclcdelta(ctxt, dwarfctxt, ls, uint64(s.Value+int64(pcline.pc)-pc), int64(pcline.value)-int64(line))
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
pc = s.Value + int64(pcline.pc)
|
|
|
|
|
line = int(pcline.value)
|
|
|
|
|
if pcfile.nextpc < pcline.nextpc {
|
|
|
|
|
epc = int64(pcfile.nextpc)
|
|
|
|
|
} else {
|
|
|
|
|
epc = int64(pcline.nextpc)
|
|
|
|
|
}
|
|
|
|
|
epc += s.Value
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
Adduint8(ctxt, ls, 0) // start extended opcode
|
2016-07-28 13:04:41 -04:00
|
|
|
dwarf.Uleb128put(dwarfctxt, ls, 1)
|
2016-08-19 22:40:38 -04:00
|
|
|
Adduint8(ctxt, ls, dwarf.DW_LNE_end_sequence)
|
2016-03-14 09:23:04 -07:00
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(dwinfo, dwarf.DW_AT_high_pc, dwarf.DW_CLS_ADDRESS, epc+1, epcs)
|
2016-03-14 09:23:04 -07:00
|
|
|
|
2016-08-22 10:33:13 -04:00
|
|
|
setuint32(ctxt, ls, unitLengthOffset, uint32(ls.Size-unitstart))
|
|
|
|
|
setuint32(ctxt, ls, headerLengthOffset, uint32(headerend-headerstart))
|
2016-03-14 09:23:04 -07:00
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
return syms, funcs
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Emit .debug_frame
|
|
|
|
|
*/
|
|
|
|
|
const (
|
2016-04-13 13:34:41 -04:00
|
|
|
dataAlignmentFactor = -4
|
2015-02-27 22:57:28 -05:00
|
|
|
)
|
|
|
|
|
|
2016-02-29 13:07:50 -09:00
|
|
|
// appendPCDeltaCFA appends per-PC CFA deltas to b and returns the final slice.
|
|
|
|
|
func appendPCDeltaCFA(b []byte, deltapc, cfa int64) []byte {
|
2016-07-28 13:04:41 -04:00
|
|
|
b = append(b, dwarf.DW_CFA_def_cfa_offset_sf)
|
|
|
|
|
b = dwarf.AppendSleb128(b, cfa/dataAlignmentFactor)
|
2016-02-29 13:07:50 -09:00
|
|
|
|
|
|
|
|
switch {
|
|
|
|
|
case deltapc < 0x40:
|
2016-07-28 13:04:41 -04:00
|
|
|
b = append(b, uint8(dwarf.DW_CFA_advance_loc+deltapc))
|
2016-02-29 13:07:50 -09:00
|
|
|
case deltapc < 0x100:
|
2016-07-28 13:04:41 -04:00
|
|
|
b = append(b, dwarf.DW_CFA_advance_loc1)
|
2016-02-29 13:07:50 -09:00
|
|
|
b = append(b, uint8(deltapc))
|
|
|
|
|
case deltapc < 0x10000:
|
2016-07-28 13:04:41 -04:00
|
|
|
b = append(b, dwarf.DW_CFA_advance_loc2)
|
2016-02-29 13:07:50 -09:00
|
|
|
b = Thearch.Append16(b, uint16(deltapc))
|
|
|
|
|
default:
|
2016-07-28 13:04:41 -04:00
|
|
|
b = append(b, dwarf.DW_CFA_advance_loc4)
|
2016-02-29 13:07:50 -09:00
|
|
|
b = Thearch.Append32(b, uint32(deltapc))
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2016-02-29 13:07:50 -09:00
|
|
|
return b
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
func writeframes(ctxt *Link, syms []*Symbol) []*Symbol {
|
|
|
|
|
var dwarfctxt dwarf.Context = dwctxt{ctxt}
|
2017-05-22 20:17:31 -04:00
|
|
|
fs := ctxt.Syms.Lookup(".debug_frame", 0)
|
|
|
|
|
fs.Type = SDWARFSECT
|
|
|
|
|
fs.R = fs.R[:0]
|
2016-07-28 13:04:41 -04:00
|
|
|
syms = append(syms, fs)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// Emit the CIE, Section 6.4.1
|
2016-04-13 13:34:41 -04:00
|
|
|
cieReserve := uint32(16)
|
2016-08-19 22:40:38 -04:00
|
|
|
if haslinkregister(ctxt) {
|
2016-04-13 13:34:41 -04:00
|
|
|
cieReserve = 32
|
|
|
|
|
}
|
2016-08-19 22:40:38 -04:00
|
|
|
Adduint32(ctxt, fs, cieReserve) // initial length, must be multiple of thearch.ptrsize
|
|
|
|
|
Adduint32(ctxt, fs, 0xffffffff) // cid.
|
|
|
|
|
Adduint8(ctxt, fs, 3) // dwarf version (appendix F)
|
|
|
|
|
Adduint8(ctxt, fs, 0) // augmentation ""
|
2016-07-28 13:04:41 -04:00
|
|
|
dwarf.Uleb128put(dwarfctxt, fs, 1) // code_alignment_factor
|
|
|
|
|
dwarf.Sleb128put(dwarfctxt, fs, dataAlignmentFactor) // all CFI offset calculations include multiplication with this factor
|
|
|
|
|
dwarf.Uleb128put(dwarfctxt, fs, int64(Thearch.Dwarfreglr)) // return_address_register
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
Adduint8(ctxt, fs, dwarf.DW_CFA_def_cfa) // Set the current frame address..
|
2016-07-28 13:04:41 -04:00
|
|
|
dwarf.Uleb128put(dwarfctxt, fs, int64(Thearch.Dwarfregsp)) // ...to use the value in the platform's SP register (defined in l.go)...
|
2016-08-19 22:40:38 -04:00
|
|
|
if haslinkregister(ctxt) {
|
2016-07-28 13:04:41 -04:00
|
|
|
dwarf.Uleb128put(dwarfctxt, fs, int64(0)) // ...plus a 0 offset.
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
Adduint8(ctxt, fs, dwarf.DW_CFA_same_value) // The platform's link register is unchanged during the prologue.
|
2016-07-28 13:04:41 -04:00
|
|
|
dwarf.Uleb128put(dwarfctxt, fs, int64(Thearch.Dwarfreglr))
|
2016-04-13 13:34:41 -04:00
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
Adduint8(ctxt, fs, dwarf.DW_CFA_val_offset) // The previous value...
|
2016-07-28 13:04:41 -04:00
|
|
|
dwarf.Uleb128put(dwarfctxt, fs, int64(Thearch.Dwarfregsp)) // ...of the platform's SP register...
|
|
|
|
|
dwarf.Uleb128put(dwarfctxt, fs, int64(0)) // ...is CFA+0.
|
2015-05-07 00:48:09 -04:00
|
|
|
} else {
|
2016-07-28 13:04:41 -04:00
|
|
|
dwarf.Uleb128put(dwarfctxt, fs, int64(SysArch.PtrSize)) // ...plus the word size (because the call instruction implicitly adds one word to the frame).
|
2016-04-13 13:34:41 -04:00
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
Adduint8(ctxt, fs, dwarf.DW_CFA_offset_extended) // The previous value...
|
2016-07-28 13:04:41 -04:00
|
|
|
dwarf.Uleb128put(dwarfctxt, fs, int64(Thearch.Dwarfreglr)) // ...of the return address...
|
|
|
|
|
dwarf.Uleb128put(dwarfctxt, fs, int64(-SysArch.PtrSize)/dataAlignmentFactor) // ...is saved at [CFA - (PtrSize/4)].
|
2015-05-07 00:48:09 -04:00
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// 4 is to exclude the length field.
|
2016-04-13 13:34:41 -04:00
|
|
|
pad := int64(cieReserve) + 4 - fs.Size
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
if pad < 0 {
|
2016-04-13 13:34:41 -04:00
|
|
|
Exitf("dwarf: cieReserve too small by %d bytes.", -pad)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-09-20 15:31:26 +12:00
|
|
|
Addbytes(fs, zeros[:pad])
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-02-29 13:07:50 -09:00
|
|
|
var deltaBuf []byte
|
2015-03-02 12:35:15 -05:00
|
|
|
var pcsp Pciter
|
2016-09-17 10:01:17 -04:00
|
|
|
for _, s := range ctxt.Textp {
|
2016-04-12 23:18:47 +03:00
|
|
|
if s.FuncInfo == nil {
|
2015-02-27 22:57:28 -05:00
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-29 13:07:50 -09:00
|
|
|
// Emit a FDE, Section 6.4.1.
|
|
|
|
|
// First build the section contents into a byte buffer.
|
|
|
|
|
deltaBuf = deltaBuf[:0]
|
2016-08-19 22:40:38 -04:00
|
|
|
for pciterinit(ctxt, &pcsp, &s.FuncInfo.Pcsp); pcsp.done == 0; pciternext(&pcsp) {
|
2015-10-10 10:57:35 +00:00
|
|
|
nextpc := pcsp.nextpc
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// pciterinit goes up to the end of the function,
|
|
|
|
|
// but DWARF expects us to stop just before the end.
|
|
|
|
|
if int64(nextpc) == s.Size {
|
|
|
|
|
nextpc--
|
|
|
|
|
if nextpc < pcsp.pc {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
if haslinkregister(ctxt) {
|
2016-04-13 13:34:41 -04:00
|
|
|
// TODO(bryanpkc): This is imprecise. In general, the instruction
|
|
|
|
|
// that stores the return address to the stack frame is not the
|
|
|
|
|
// same one that allocates the frame.
|
|
|
|
|
if pcsp.value > 0 {
|
|
|
|
|
// The return address is preserved at (CFA-frame_size)
|
|
|
|
|
// after a stack frame has been allocated.
|
2016-07-28 13:04:41 -04:00
|
|
|
deltaBuf = append(deltaBuf, dwarf.DW_CFA_offset_extended_sf)
|
|
|
|
|
deltaBuf = dwarf.AppendUleb128(deltaBuf, uint64(Thearch.Dwarfreglr))
|
|
|
|
|
deltaBuf = dwarf.AppendSleb128(deltaBuf, -int64(pcsp.value)/dataAlignmentFactor)
|
2016-04-13 13:34:41 -04:00
|
|
|
} else {
|
|
|
|
|
// The return address is restored into the link register
|
|
|
|
|
// when a stack frame has been de-allocated.
|
2016-07-28 13:04:41 -04:00
|
|
|
deltaBuf = append(deltaBuf, dwarf.DW_CFA_same_value)
|
|
|
|
|
deltaBuf = dwarf.AppendUleb128(deltaBuf, uint64(Thearch.Dwarfreglr))
|
2016-04-13 13:34:41 -04:00
|
|
|
}
|
2016-02-29 13:07:50 -09:00
|
|
|
deltaBuf = appendPCDeltaCFA(deltaBuf, int64(nextpc)-int64(pcsp.pc), int64(pcsp.value))
|
2015-05-07 00:48:09 -04:00
|
|
|
} else {
|
2016-04-06 12:01:40 -07:00
|
|
|
deltaBuf = appendPCDeltaCFA(deltaBuf, int64(nextpc)-int64(pcsp.pc), int64(SysArch.PtrSize)+int64(pcsp.value))
|
2015-05-07 00:48:09 -04:00
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2016-04-06 12:01:40 -07:00
|
|
|
pad := int(Rnd(int64(len(deltaBuf)), int64(SysArch.PtrSize))) - len(deltaBuf)
|
2016-02-29 13:07:50 -09:00
|
|
|
deltaBuf = append(deltaBuf, zeros[:pad]...)
|
|
|
|
|
|
|
|
|
|
// Emit the FDE header, Section 6.4.1.
|
|
|
|
|
// 4 bytes: length, must be multiple of thearch.ptrsize
|
|
|
|
|
// 4 bytes: Pointer to the CIE above, at offset 0
|
|
|
|
|
// ptrsize: initial location
|
|
|
|
|
// ptrsize: address range
|
2016-08-19 22:40:38 -04:00
|
|
|
Adduint32(ctxt, fs, uint32(4+2*SysArch.PtrSize+len(deltaBuf))) // length (excludes itself)
|
2015-02-27 22:57:28 -05:00
|
|
|
if Linkmode == LinkExternal {
|
2017-05-22 20:17:31 -04:00
|
|
|
adddwarfref(ctxt, fs, fs, 4)
|
2015-02-27 22:57:28 -05:00
|
|
|
} else {
|
2016-08-19 22:40:38 -04:00
|
|
|
Adduint32(ctxt, fs, 0) // CIE offset
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2016-08-19 22:40:38 -04:00
|
|
|
Addaddr(ctxt, fs, s)
|
|
|
|
|
adduintxx(ctxt, fs, uint64(s.Size), SysArch.PtrSize) // address range
|
2016-09-20 15:31:26 +12:00
|
|
|
Addbytes(fs, deltaBuf)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2016-07-28 13:04:41 -04:00
|
|
|
return syms
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2017-05-02 16:46:01 +02:00
|
|
|
func writeranges(ctxt *Link, syms []*Symbol) []*Symbol {
|
2017-05-22 20:17:31 -04:00
|
|
|
empty := true
|
2017-05-02 16:46:01 +02:00
|
|
|
for _, s := range ctxt.Textp {
|
|
|
|
|
rangeSym := ctxt.Syms.Lookup(dwarf.RangePrefix+s.Name, int(s.Version))
|
2017-05-22 20:17:31 -04:00
|
|
|
if rangeSym.Size == 0 {
|
|
|
|
|
continue
|
2017-05-02 16:46:01 +02:00
|
|
|
}
|
2017-05-22 20:17:31 -04:00
|
|
|
rangeSym.Attr |= AttrReachable | AttrNotInSymbolTable
|
|
|
|
|
rangeSym.Type = SDWARFRANGE
|
|
|
|
|
syms = append(syms, rangeSym)
|
|
|
|
|
empty = false
|
2017-05-02 16:46:01 +02:00
|
|
|
}
|
2017-05-22 20:17:31 -04:00
|
|
|
if !empty {
|
2017-05-02 16:46:01 +02:00
|
|
|
// PE does not like empty sections
|
2017-05-22 20:17:31 -04:00
|
|
|
rangesec := ctxt.Syms.Lookup(".debug_ranges", 0)
|
|
|
|
|
rangesec.Type = SDWARFRANGE
|
|
|
|
|
rangesec.Attr |= AttrReachable
|
|
|
|
|
rangesec.R = rangesec.R[:0]
|
|
|
|
|
|
2017-05-02 16:46:01 +02:00
|
|
|
syms = append(syms, rangesec)
|
|
|
|
|
}
|
|
|
|
|
return syms
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-27 22:57:28 -05:00
|
|
|
/*
|
|
|
|
|
* Walk DWarfDebugInfoEntries, and emit .debug_info
|
|
|
|
|
*/
|
|
|
|
|
const (
|
|
|
|
|
COMPUNITHEADERSIZE = 4 + 2 + 4 + 1
|
|
|
|
|
)
|
|
|
|
|
|
2017-05-22 20:17:31 -04:00
|
|
|
func writeinfo(ctxt *Link, syms []*Symbol, funcs []*Symbol, abbrevsym *Symbol) []*Symbol {
|
|
|
|
|
infosec := ctxt.Syms.Lookup(".debug_info", 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
infosec.R = infosec.R[:0]
|
2017-04-19 15:15:35 +12:00
|
|
|
infosec.Type = SDWARFINFO
|
2016-03-14 09:23:04 -07:00
|
|
|
infosec.Attr |= AttrReachable
|
2016-07-28 13:04:41 -04:00
|
|
|
syms = append(syms, infosec)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-05-22 20:17:31 -04:00
|
|
|
arangessec := ctxt.Syms.Lookup(".dwarfaranges", 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
arangessec.R = arangessec.R[:0]
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
var dwarfctxt dwarf.Context = dwctxt{ctxt}
|
2016-07-28 13:04:41 -04:00
|
|
|
|
|
|
|
|
for compunit := dwroot.Child; compunit != nil; compunit = compunit.Link {
|
|
|
|
|
s := dtolsym(compunit.Sym)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// Write .debug_info Compilation Unit Header (sec 7.5.1)
|
|
|
|
|
// Fields marked with (*) must be changed for 64-bit dwarf
|
|
|
|
|
// This must match COMPUNITHEADERSIZE above.
|
2016-08-19 22:40:38 -04:00
|
|
|
Adduint32(ctxt, s, 0) // unit_length (*), will be filled in later.
|
2017-05-24 17:43:08 -04:00
|
|
|
Adduint16(ctxt, s, 4) // dwarf version (appendix F)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// debug_abbrev_offset (*)
|
2016-08-19 22:40:38 -04:00
|
|
|
adddwarfref(ctxt, s, abbrevsym, 4)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
Adduint8(ctxt, s, uint8(SysArch.PtrSize)) // address_size
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
dwarf.Uleb128put(dwarfctxt, s, int64(compunit.Abbrev))
|
|
|
|
|
dwarf.PutAttrs(dwarfctxt, s, compunit.Abbrev, compunit.Attr)
|
|
|
|
|
|
2016-08-19 11:35:54 -04:00
|
|
|
cu := []*Symbol{s}
|
2016-07-28 13:04:41 -04:00
|
|
|
if funcs != nil {
|
|
|
|
|
cu = append(cu, funcs...)
|
|
|
|
|
funcs = nil
|
|
|
|
|
}
|
2016-08-19 22:40:38 -04:00
|
|
|
cu = putdies(ctxt, dwarfctxt, cu, compunit.Child)
|
2016-07-28 13:04:41 -04:00
|
|
|
var cusize int64
|
|
|
|
|
for _, child := range cu {
|
2016-03-14 09:23:04 -07:00
|
|
|
cusize += child.Size
|
|
|
|
|
}
|
2016-07-28 13:04:41 -04:00
|
|
|
cusize -= 4 // exclude the length field.
|
2016-08-19 22:40:38 -04:00
|
|
|
setuint32(ctxt, s, 0, uint32(cusize))
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(compunit, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, cusize, 0)
|
|
|
|
|
syms = append(syms, cu...)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2016-07-28 13:04:41 -04:00
|
|
|
return syms
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Emit .debug_pubnames/_types. _info must have been written before,
|
|
|
|
|
* because we need die->offs and infoo/infosize;
|
|
|
|
|
*/
|
2016-07-28 13:04:41 -04:00
|
|
|
func ispubname(die *dwarf.DWDie) bool {
|
|
|
|
|
switch die.Abbrev {
|
|
|
|
|
case dwarf.DW_ABRV_FUNCTION, dwarf.DW_ABRV_VARIABLE:
|
|
|
|
|
a := getattr(die, dwarf.DW_AT_external)
|
|
|
|
|
return a != nil && a.Value != 0
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
func ispubtype(die *dwarf.DWDie) bool {
|
|
|
|
|
return die.Abbrev >= dwarf.DW_ABRV_NULLTYPE
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
func writepub(ctxt *Link, sname string, ispub func(*dwarf.DWDie) bool, syms []*Symbol) []*Symbol {
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
s := ctxt.Syms.Lookup(sname, 0)
|
2017-04-19 15:15:35 +12:00
|
|
|
s.Type = SDWARFSECT
|
2016-07-28 13:04:41 -04:00
|
|
|
syms = append(syms, s)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
for compunit := dwroot.Child; compunit != nil; compunit = compunit.Link {
|
2016-03-14 09:23:04 -07:00
|
|
|
sectionstart := s.Size
|
2016-07-28 13:04:41 -04:00
|
|
|
culength := uint32(getattr(compunit, dwarf.DW_AT_byte_size).Value) + 4
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// Write .debug_pubnames/types Header (sec 6.1.1)
|
2016-08-19 22:40:38 -04:00
|
|
|
Adduint32(ctxt, s, 0) // unit_length (*), will be filled in later.
|
|
|
|
|
Adduint16(ctxt, s, 2) // dwarf version (appendix F)
|
|
|
|
|
adddwarfref(ctxt, s, dtolsym(compunit.Sym), 4) // debug_info_offset (of the Comp unit Header)
|
|
|
|
|
Adduint32(ctxt, s, culength) // debug_info_length
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
for die := compunit.Child; die != nil; die = die.Link {
|
2015-02-27 22:57:28 -05:00
|
|
|
if !ispub(die) {
|
|
|
|
|
continue
|
|
|
|
|
}
|
2016-07-28 13:04:41 -04:00
|
|
|
dwa := getattr(die, dwarf.DW_AT_name)
|
|
|
|
|
name := dwa.Data.(string)
|
|
|
|
|
if die.Sym == nil {
|
2016-03-14 09:23:04 -07:00
|
|
|
fmt.Println("Missing sym for ", name)
|
|
|
|
|
}
|
2016-08-19 22:40:38 -04:00
|
|
|
adddwarfref(ctxt, s, dtolsym(die.Sym), 4)
|
2016-09-20 15:31:26 +12:00
|
|
|
Addstring(s, name)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
Adduint32(ctxt, s, 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
setuint32(ctxt, s, sectionstart, uint32(s.Size-sectionstart)-4) // exclude the length field.
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
return syms
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* emit .debug_aranges. _info must have been written before,
|
2016-07-28 13:04:41 -04:00
|
|
|
* because we need die->offs of dwarf.DW_globals.
|
2015-02-27 22:57:28 -05:00
|
|
|
*/
|
2016-08-19 22:40:38 -04:00
|
|
|
func writearanges(ctxt *Link, syms []*Symbol) []*Symbol {
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
s := ctxt.Syms.Lookup(".debug_aranges", 0)
|
2017-04-19 15:15:35 +12:00
|
|
|
s.Type = SDWARFSECT
|
2016-02-10 16:51:23 -08:00
|
|
|
// The first tuple is aligned to a multiple of the size of a single tuple
|
|
|
|
|
// (twice the size of an address)
|
2016-04-06 12:01:40 -07:00
|
|
|
headersize := int(Rnd(4+2+4+1+1, int64(SysArch.PtrSize*2))) // don't count unit_length field itself
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
for compunit := dwroot.Child; compunit != nil; compunit = compunit.Link {
|
|
|
|
|
b := getattr(compunit, dwarf.DW_AT_low_pc)
|
2015-02-27 22:57:28 -05:00
|
|
|
if b == nil {
|
|
|
|
|
continue
|
|
|
|
|
}
|
2016-07-28 13:04:41 -04:00
|
|
|
e := getattr(compunit, dwarf.DW_AT_high_pc)
|
2015-02-27 22:57:28 -05:00
|
|
|
if e == nil {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Write .debug_aranges Header + entry (sec 6.1.2)
|
2016-04-06 12:01:40 -07:00
|
|
|
unitlength := uint32(headersize) + 4*uint32(SysArch.PtrSize) - 4
|
2016-08-19 22:40:38 -04:00
|
|
|
Adduint32(ctxt, s, unitlength) // unit_length (*)
|
|
|
|
|
Adduint16(ctxt, s, 2) // dwarf version (appendix F)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
adddwarfref(ctxt, s, dtolsym(compunit.Sym), 4)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
Adduint8(ctxt, s, uint8(SysArch.PtrSize)) // address_size
|
|
|
|
|
Adduint8(ctxt, s, 0) // segment_size
|
2016-03-14 09:23:04 -07:00
|
|
|
padding := headersize - (4 + 2 + 4 + 1 + 1)
|
|
|
|
|
for i := 0; i < padding; i++ {
|
2016-08-19 22:40:38 -04:00
|
|
|
Adduint8(ctxt, s, 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
Addaddrplus(ctxt, s, b.Data.(*Symbol), b.Value-(b.Data.(*Symbol)).Value)
|
|
|
|
|
adduintxx(ctxt, s, uint64(e.Value-b.Value), SysArch.PtrSize)
|
|
|
|
|
adduintxx(ctxt, s, 0, SysArch.PtrSize)
|
|
|
|
|
adduintxx(ctxt, s, 0, SysArch.PtrSize)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2016-03-14 09:23:04 -07:00
|
|
|
if s.Size > 0 {
|
2016-07-28 13:04:41 -04:00
|
|
|
syms = append(syms, s)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2016-07-28 13:04:41 -04:00
|
|
|
return syms
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
func writegdbscript(ctxt *Link, syms []*Symbol) []*Symbol {
|
2017-05-11 11:55:59 +10:00
|
|
|
if Linkmode == LinkExternal && Headtype == objabi.Hwindows && Buildmode == BuildmodeCArchive {
|
2017-05-07 11:04:24 -07:00
|
|
|
// gcc on Windows places .debug_gdb_scripts in the wrong location, which
|
|
|
|
|
// causes the program not to run. See https://golang.org/issue/20183
|
2017-05-11 11:55:59 +10:00
|
|
|
// Non c-archives can avoid this issue via a linker script
|
|
|
|
|
// (see fix near writeGDBLinkerScript).
|
|
|
|
|
// c-archive users would need to specify the linker script manually.
|
|
|
|
|
// For UX it's better not to deal with this.
|
2017-05-04 16:14:59 +03:00
|
|
|
return syms
|
|
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-03-14 09:23:04 -07:00
|
|
|
if gdbscript != "" {
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
s := ctxt.Syms.Lookup(".debug_gdb_scripts", 0)
|
2017-04-19 15:15:35 +12:00
|
|
|
s.Type = SDWARFSECT
|
2016-07-28 13:04:41 -04:00
|
|
|
syms = append(syms, s)
|
2016-08-19 22:40:38 -04:00
|
|
|
Adduint8(ctxt, s, 1) // magic 1 byte?
|
2016-09-20 15:31:26 +12:00
|
|
|
Addstring(s, gdbscript)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
return syms
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
var prototypedies map[string]*dwarf.DWDie
|
2015-04-08 12:55:34 -07:00
|
|
|
|
2015-02-27 22:57:28 -05:00
|
|
|
/*
|
|
|
|
|
* This is the main entry point for generating dwarf. After emitting
|
|
|
|
|
* the mandatory debug_abbrev section, it calls writelines() to set up
|
|
|
|
|
* the per-compilation unit part of the DIE tree, while simultaneously
|
|
|
|
|
* emitting the debug_line section. When the final tree contains
|
|
|
|
|
* forward references, it will write the debug_info section in 2
|
|
|
|
|
* passes.
|
|
|
|
|
*
|
|
|
|
|
*/
|
2016-08-19 22:40:38 -04:00
|
|
|
func dwarfgeneratedebugsyms(ctxt *Link) {
|
2016-08-21 18:34:24 -04:00
|
|
|
if *FlagW { // disable dwarf
|
2015-02-27 22:57:28 -05:00
|
|
|
return
|
|
|
|
|
}
|
2017-04-18 12:53:25 -07:00
|
|
|
if *FlagS && Headtype != objabi.Hdarwin {
|
2016-04-07 14:00:00 -04:00
|
|
|
return
|
|
|
|
|
}
|
2017-04-18 12:53:25 -07:00
|
|
|
if Headtype == objabi.Hplan9 {
|
2016-03-14 09:23:04 -07:00
|
|
|
return
|
|
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2015-04-08 12:55:34 -07:00
|
|
|
if Linkmode == LinkExternal {
|
2017-02-08 12:47:43 +11:00
|
|
|
switch {
|
|
|
|
|
case Iself:
|
2017-04-18 12:53:25 -07:00
|
|
|
case Headtype == objabi.Hdarwin:
|
|
|
|
|
case Headtype == objabi.Hwindows:
|
2017-02-08 12:47:43 +11:00
|
|
|
default:
|
2015-04-08 12:55:34 -07:00
|
|
|
return
|
|
|
|
|
}
|
2016-03-14 09:23:04 -07:00
|
|
|
}
|
2015-04-08 12:55:34 -07:00
|
|
|
|
2016-08-21 18:25:28 -04:00
|
|
|
if ctxt.Debugvlog != 0 {
|
2017-04-18 12:53:25 -07:00
|
|
|
ctxt.Logf("%5.2f dwarf\n", Cputime())
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
// Forctxt.Diagnostic messages.
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(&dwtypes, dwarf.DW_AT_name, dwarf.DW_CLS_STRING, int64(len("dwtypes")), "dwtypes")
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// Some types that must exist to define other ones.
|
2016-08-19 22:40:38 -04:00
|
|
|
newdie(ctxt, &dwtypes, dwarf.DW_ABRV_NULLTYPE, "<unspecified>", 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
newdie(ctxt, &dwtypes, dwarf.DW_ABRV_NULLTYPE, "void", 0)
|
|
|
|
|
newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BARE_PTRTYPE, "unsafe.Pointer", 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
die := newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, "uintptr", 0) // needed for array size
|
2016-07-28 13:04:41 -04:00
|
|
|
newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_unsigned, 0)
|
|
|
|
|
newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, int64(SysArch.PtrSize), 0)
|
2017-04-18 12:53:25 -07:00
|
|
|
newattr(die, dwarf.DW_AT_go_kind, dwarf.DW_CLS_CONSTANT, objabi.KindUintptr, 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-03-14 09:23:04 -07:00
|
|
|
// Prototypes needed for type synthesis.
|
2016-07-28 13:04:41 -04:00
|
|
|
prototypedies = map[string]*dwarf.DWDie{
|
2016-03-14 09:23:04 -07:00
|
|
|
"type.runtime.stringStructDWARF": nil,
|
|
|
|
|
"type.runtime.slice": nil,
|
|
|
|
|
"type.runtime.hmap": nil,
|
|
|
|
|
"type.runtime.bmap": nil,
|
|
|
|
|
"type.runtime.sudog": nil,
|
|
|
|
|
"type.runtime.waitq": nil,
|
|
|
|
|
"type.runtime.hchan": nil,
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-27 22:57:28 -05:00
|
|
|
// Needed by the prettyprinter code for interface inspection.
|
2017-03-18 15:09:40 +01:00
|
|
|
for _, typ := range []string{
|
|
|
|
|
"type.runtime._type",
|
|
|
|
|
"type.runtime.arraytype",
|
|
|
|
|
"type.runtime.chantype",
|
|
|
|
|
"type.runtime.functype",
|
|
|
|
|
"type.runtime.maptype",
|
|
|
|
|
"type.runtime.ptrtype",
|
|
|
|
|
"type.runtime.slicetype",
|
|
|
|
|
"type.runtime.structtype",
|
|
|
|
|
"type.runtime.interfacetype",
|
|
|
|
|
"type.runtime.itab",
|
|
|
|
|
"type.runtime.imethod"} {
|
|
|
|
|
defgotype(ctxt, lookupOrDiag(ctxt, typ))
|
|
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
genasmsym(ctxt, defdwsymb)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-05-22 20:17:31 -04:00
|
|
|
abbrev := writeabbrev(ctxt)
|
|
|
|
|
syms := []*Symbol{abbrev}
|
2016-08-19 22:40:38 -04:00
|
|
|
syms, funcs := writelines(ctxt, syms)
|
|
|
|
|
syms = writeframes(ctxt, syms)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
synthesizestringtypes(ctxt, dwtypes.Child)
|
|
|
|
|
synthesizeslicetypes(ctxt, dwtypes.Child)
|
|
|
|
|
synthesizemaptypes(ctxt, dwtypes.Child)
|
|
|
|
|
synthesizechantypes(ctxt, dwtypes.Child)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-07-28 13:04:41 -04:00
|
|
|
reversetree(&dwroot.Child)
|
|
|
|
|
reversetree(&dwtypes.Child)
|
|
|
|
|
reversetree(&dwglobals.Child)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
movetomodule(&dwtypes)
|
|
|
|
|
movetomodule(&dwglobals)
|
|
|
|
|
|
2016-03-14 09:23:04 -07:00
|
|
|
// Need to reorder symbols so SDWARFINFO is after all SDWARFSECT
|
|
|
|
|
// (but we need to generate dies before writepub)
|
2017-05-22 20:17:31 -04:00
|
|
|
infosyms := writeinfo(ctxt, nil, funcs, abbrev)
|
2016-07-28 13:04:41 -04:00
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
syms = writepub(ctxt, ".debug_pubnames", ispubname, syms)
|
|
|
|
|
syms = writepub(ctxt, ".debug_pubtypes", ispubtype, syms)
|
|
|
|
|
syms = writearanges(ctxt, syms)
|
|
|
|
|
syms = writegdbscript(ctxt, syms)
|
2016-07-28 13:04:41 -04:00
|
|
|
syms = append(syms, infosyms...)
|
[dev.debug] cmd/compile: better DWARF with optimizations on
Debuggers use DWARF information to find local variables on the
stack and in registers. Prior to this CL, the DWARF information for
functions claimed that all variables were on the stack at all times.
That's incorrect when optimizations are enabled, and results in
debuggers showing data that is out of date or complete gibberish.
After this CL, the compiler is capable of representing variable
locations more accurately, and attempts to do so. Due to limitations of
the SSA backend, it's not possible to be completely correct.
There are a number of problems in the current design. One of the easier
to understand is that variable names currently must be attached to an
SSA value, but not all assignments in the source code actually result
in machine code. For example:
type myint int
var a int
b := myint(int)
and
b := (*uint64)(unsafe.Pointer(a))
don't generate machine code because the underlying representation is the
same, so the correct value of b will not be set when the user would
expect.
Generating the more precise debug information is behind a flag,
dwarflocationlists. Because of the issues described above, setting the
flag may not make the debugging experience much better, and may actually
make it worse in cases where the variable actually is on the stack and
the more complicated analysis doesn't realize it.
A number of changes are included:
- Add a new pseudo-instruction, RegKill, which indicates that the value
in the register has been clobbered.
- Adjust regalloc to emit RegKills in the right places. Significantly,
this means that phis are mixed with StoreReg and RegKills after
regalloc.
- Track variable decomposition in ssa.LocalSlots.
- After the SSA backend is done, analyze the result and build location
lists for each LocalSlot.
- After assembly is done, update the location lists with the assembled
PC offsets, recompose variables, and build DWARF location lists. Emit the
list as a new linker symbol, one per function.
- In the linker, aggregate the location lists into a .debug_loc section.
TODO:
- currently disabled for non-X86/AMD64 because there are no data tables.
go build -toolexec 'toolstash -cmp' -a std succeeds.
With -dwarflocationlists false:
before: f02812195637909ff675782c0b46836a8ff01976
after: 06f61e8112a42ac34fb80e0c818b3cdb84a5e7ec
benchstat -geomean /tmp/220352263 /tmp/621364410
completed 15 of 15, estimated time remaining 0s (eta 3:52PM)
name old time/op new time/op delta
Template 199ms ± 3% 198ms ± 2% ~ (p=0.400 n=15+14)
Unicode 96.6ms ± 5% 96.4ms ± 5% ~ (p=0.838 n=15+15)
GoTypes 653ms ± 2% 647ms ± 2% ~ (p=0.102 n=15+14)
Flate 133ms ± 6% 129ms ± 3% -2.62% (p=0.041 n=15+15)
GoParser 164ms ± 5% 159ms ± 3% -3.05% (p=0.000 n=15+15)
Reflect 428ms ± 4% 422ms ± 3% ~ (p=0.156 n=15+13)
Tar 123ms ±10% 124ms ± 8% ~ (p=0.461 n=15+15)
XML 228ms ± 3% 224ms ± 3% -1.57% (p=0.045 n=15+15)
[Geo mean] 206ms 377ms +82.86%
name old user-time/op new user-time/op delta
Template 292ms ±10% 301ms ±12% ~ (p=0.189 n=15+15)
Unicode 166ms ±37% 158ms ±14% ~ (p=0.418 n=15+14)
GoTypes 962ms ± 6% 963ms ± 7% ~ (p=0.976 n=15+15)
Flate 207ms ±19% 200ms ±14% ~ (p=0.345 n=14+15)
GoParser 246ms ±22% 240ms ±15% ~ (p=0.587 n=15+15)
Reflect 611ms ±13% 587ms ±14% ~ (p=0.085 n=15+13)
Tar 211ms ±12% 217ms ±14% ~ (p=0.355 n=14+15)
XML 335ms ±15% 320ms ±18% ~ (p=0.169 n=15+15)
[Geo mean] 317ms 583ms +83.72%
name old alloc/op new alloc/op delta
Template 40.2MB ± 0% 40.2MB ± 0% -0.15% (p=0.000 n=14+15)
Unicode 29.2MB ± 0% 29.3MB ± 0% ~ (p=0.624 n=15+15)
GoTypes 114MB ± 0% 114MB ± 0% -0.15% (p=0.000 n=15+14)
Flate 25.7MB ± 0% 25.6MB ± 0% -0.18% (p=0.000 n=13+15)
GoParser 32.2MB ± 0% 32.2MB ± 0% -0.14% (p=0.003 n=15+15)
Reflect 77.8MB ± 0% 77.9MB ± 0% ~ (p=0.061 n=15+15)
Tar 27.1MB ± 0% 27.0MB ± 0% -0.11% (p=0.029 n=15+15)
XML 42.7MB ± 0% 42.5MB ± 0% -0.29% (p=0.000 n=15+15)
[Geo mean] 42.1MB 75.0MB +78.05%
name old allocs/op new allocs/op delta
Template 402k ± 1% 398k ± 0% -0.91% (p=0.000 n=15+15)
Unicode 344k ± 1% 344k ± 0% ~ (p=0.715 n=15+14)
GoTypes 1.18M ± 0% 1.17M ± 0% -0.91% (p=0.000 n=15+14)
Flate 243k ± 0% 240k ± 1% -1.05% (p=0.000 n=13+15)
GoParser 327k ± 1% 324k ± 1% -0.96% (p=0.000 n=15+15)
Reflect 984k ± 1% 982k ± 0% ~ (p=0.050 n=15+15)
Tar 261k ± 1% 259k ± 1% -0.77% (p=0.000 n=15+15)
XML 411k ± 0% 404k ± 1% -1.55% (p=0.000 n=15+15)
[Geo mean] 439k 755k +72.01%
name old text-bytes new text-bytes delta
HelloSize 694kB ± 0% 694kB ± 0% -0.00% (p=0.000 n=15+15)
name old data-bytes new data-bytes delta
HelloSize 5.55kB ± 0% 5.55kB ± 0% ~ (all equal)
name old bss-bytes new bss-bytes delta
HelloSize 133kB ± 0% 133kB ± 0% ~ (all equal)
name old exe-bytes new exe-bytes delta
HelloSize 1.04MB ± 0% 1.04MB ± 0% ~ (all equal)
Change-Id: I991fc553ef175db46bb23b2128317bbd48de70d8
Reviewed-on: https://go-review.googlesource.com/41770
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
2017-07-21 18:30:19 -04:00
|
|
|
syms = collectlocs(ctxt, syms, funcs)
|
2017-05-22 20:17:31 -04:00
|
|
|
syms = writeranges(ctxt, syms)
|
2016-04-22 10:31:14 +12:00
|
|
|
dwarfp = syms
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
[dev.debug] cmd/compile: better DWARF with optimizations on
Debuggers use DWARF information to find local variables on the
stack and in registers. Prior to this CL, the DWARF information for
functions claimed that all variables were on the stack at all times.
That's incorrect when optimizations are enabled, and results in
debuggers showing data that is out of date or complete gibberish.
After this CL, the compiler is capable of representing variable
locations more accurately, and attempts to do so. Due to limitations of
the SSA backend, it's not possible to be completely correct.
There are a number of problems in the current design. One of the easier
to understand is that variable names currently must be attached to an
SSA value, but not all assignments in the source code actually result
in machine code. For example:
type myint int
var a int
b := myint(int)
and
b := (*uint64)(unsafe.Pointer(a))
don't generate machine code because the underlying representation is the
same, so the correct value of b will not be set when the user would
expect.
Generating the more precise debug information is behind a flag,
dwarflocationlists. Because of the issues described above, setting the
flag may not make the debugging experience much better, and may actually
make it worse in cases where the variable actually is on the stack and
the more complicated analysis doesn't realize it.
A number of changes are included:
- Add a new pseudo-instruction, RegKill, which indicates that the value
in the register has been clobbered.
- Adjust regalloc to emit RegKills in the right places. Significantly,
this means that phis are mixed with StoreReg and RegKills after
regalloc.
- Track variable decomposition in ssa.LocalSlots.
- After the SSA backend is done, analyze the result and build location
lists for each LocalSlot.
- After assembly is done, update the location lists with the assembled
PC offsets, recompose variables, and build DWARF location lists. Emit the
list as a new linker symbol, one per function.
- In the linker, aggregate the location lists into a .debug_loc section.
TODO:
- currently disabled for non-X86/AMD64 because there are no data tables.
go build -toolexec 'toolstash -cmp' -a std succeeds.
With -dwarflocationlists false:
before: f02812195637909ff675782c0b46836a8ff01976
after: 06f61e8112a42ac34fb80e0c818b3cdb84a5e7ec
benchstat -geomean /tmp/220352263 /tmp/621364410
completed 15 of 15, estimated time remaining 0s (eta 3:52PM)
name old time/op new time/op delta
Template 199ms ± 3% 198ms ± 2% ~ (p=0.400 n=15+14)
Unicode 96.6ms ± 5% 96.4ms ± 5% ~ (p=0.838 n=15+15)
GoTypes 653ms ± 2% 647ms ± 2% ~ (p=0.102 n=15+14)
Flate 133ms ± 6% 129ms ± 3% -2.62% (p=0.041 n=15+15)
GoParser 164ms ± 5% 159ms ± 3% -3.05% (p=0.000 n=15+15)
Reflect 428ms ± 4% 422ms ± 3% ~ (p=0.156 n=15+13)
Tar 123ms ±10% 124ms ± 8% ~ (p=0.461 n=15+15)
XML 228ms ± 3% 224ms ± 3% -1.57% (p=0.045 n=15+15)
[Geo mean] 206ms 377ms +82.86%
name old user-time/op new user-time/op delta
Template 292ms ±10% 301ms ±12% ~ (p=0.189 n=15+15)
Unicode 166ms ±37% 158ms ±14% ~ (p=0.418 n=15+14)
GoTypes 962ms ± 6% 963ms ± 7% ~ (p=0.976 n=15+15)
Flate 207ms ±19% 200ms ±14% ~ (p=0.345 n=14+15)
GoParser 246ms ±22% 240ms ±15% ~ (p=0.587 n=15+15)
Reflect 611ms ±13% 587ms ±14% ~ (p=0.085 n=15+13)
Tar 211ms ±12% 217ms ±14% ~ (p=0.355 n=14+15)
XML 335ms ±15% 320ms ±18% ~ (p=0.169 n=15+15)
[Geo mean] 317ms 583ms +83.72%
name old alloc/op new alloc/op delta
Template 40.2MB ± 0% 40.2MB ± 0% -0.15% (p=0.000 n=14+15)
Unicode 29.2MB ± 0% 29.3MB ± 0% ~ (p=0.624 n=15+15)
GoTypes 114MB ± 0% 114MB ± 0% -0.15% (p=0.000 n=15+14)
Flate 25.7MB ± 0% 25.6MB ± 0% -0.18% (p=0.000 n=13+15)
GoParser 32.2MB ± 0% 32.2MB ± 0% -0.14% (p=0.003 n=15+15)
Reflect 77.8MB ± 0% 77.9MB ± 0% ~ (p=0.061 n=15+15)
Tar 27.1MB ± 0% 27.0MB ± 0% -0.11% (p=0.029 n=15+15)
XML 42.7MB ± 0% 42.5MB ± 0% -0.29% (p=0.000 n=15+15)
[Geo mean] 42.1MB 75.0MB +78.05%
name old allocs/op new allocs/op delta
Template 402k ± 1% 398k ± 0% -0.91% (p=0.000 n=15+15)
Unicode 344k ± 1% 344k ± 0% ~ (p=0.715 n=15+14)
GoTypes 1.18M ± 0% 1.17M ± 0% -0.91% (p=0.000 n=15+14)
Flate 243k ± 0% 240k ± 1% -1.05% (p=0.000 n=13+15)
GoParser 327k ± 1% 324k ± 1% -0.96% (p=0.000 n=15+15)
Reflect 984k ± 1% 982k ± 0% ~ (p=0.050 n=15+15)
Tar 261k ± 1% 259k ± 1% -0.77% (p=0.000 n=15+15)
XML 411k ± 0% 404k ± 1% -1.55% (p=0.000 n=15+15)
[Geo mean] 439k 755k +72.01%
name old text-bytes new text-bytes delta
HelloSize 694kB ± 0% 694kB ± 0% -0.00% (p=0.000 n=15+15)
name old data-bytes new data-bytes delta
HelloSize 5.55kB ± 0% 5.55kB ± 0% ~ (all equal)
name old bss-bytes new bss-bytes delta
HelloSize 133kB ± 0% 133kB ± 0% ~ (all equal)
name old exe-bytes new exe-bytes delta
HelloSize 1.04MB ± 0% 1.04MB ± 0% ~ (all equal)
Change-Id: I991fc553ef175db46bb23b2128317bbd48de70d8
Reviewed-on: https://go-review.googlesource.com/41770
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
2017-07-21 18:30:19 -04:00
|
|
|
func collectlocs(ctxt *Link, syms []*Symbol, funcs []*Symbol) []*Symbol {
|
|
|
|
|
empty := true
|
|
|
|
|
for _, fn := range funcs {
|
|
|
|
|
for _, reloc := range fn.R {
|
|
|
|
|
if reloc.Type == objabi.R_DWARFREF && strings.HasPrefix(reloc.Sym.Name, dwarf.LocPrefix) {
|
|
|
|
|
reloc.Sym.Attr |= AttrReachable | AttrNotInSymbolTable
|
|
|
|
|
syms = append(syms, reloc.Sym)
|
|
|
|
|
empty = false
|
|
|
|
|
// One location list entry per function, but many relocations to it. Don't duplicate.
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Don't emit .debug_loc if it's empty -- it makes the ARM linker mad.
|
|
|
|
|
if !empty {
|
|
|
|
|
locsym := ctxt.Syms.Lookup(".debug_loc", 0)
|
|
|
|
|
locsym.R = locsym.R[:0]
|
|
|
|
|
locsym.Type = SDWARFLOC
|
|
|
|
|
locsym.Attr |= AttrReachable
|
|
|
|
|
syms = append(syms, locsym)
|
|
|
|
|
}
|
|
|
|
|
return syms
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-27 22:57:28 -05:00
|
|
|
/*
|
|
|
|
|
* Elf.
|
|
|
|
|
*/
|
2016-08-19 22:40:38 -04:00
|
|
|
func dwarfaddshstrings(ctxt *Link, shstrtab *Symbol) {
|
2016-08-21 18:34:24 -04:00
|
|
|
if *FlagW { // disable dwarf
|
2015-02-27 22:57:28 -05:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-20 15:31:26 +12:00
|
|
|
Addstring(shstrtab, ".debug_abbrev")
|
|
|
|
|
Addstring(shstrtab, ".debug_aranges")
|
|
|
|
|
Addstring(shstrtab, ".debug_frame")
|
|
|
|
|
Addstring(shstrtab, ".debug_info")
|
[dev.debug] cmd/compile: better DWARF with optimizations on
Debuggers use DWARF information to find local variables on the
stack and in registers. Prior to this CL, the DWARF information for
functions claimed that all variables were on the stack at all times.
That's incorrect when optimizations are enabled, and results in
debuggers showing data that is out of date or complete gibberish.
After this CL, the compiler is capable of representing variable
locations more accurately, and attempts to do so. Due to limitations of
the SSA backend, it's not possible to be completely correct.
There are a number of problems in the current design. One of the easier
to understand is that variable names currently must be attached to an
SSA value, but not all assignments in the source code actually result
in machine code. For example:
type myint int
var a int
b := myint(int)
and
b := (*uint64)(unsafe.Pointer(a))
don't generate machine code because the underlying representation is the
same, so the correct value of b will not be set when the user would
expect.
Generating the more precise debug information is behind a flag,
dwarflocationlists. Because of the issues described above, setting the
flag may not make the debugging experience much better, and may actually
make it worse in cases where the variable actually is on the stack and
the more complicated analysis doesn't realize it.
A number of changes are included:
- Add a new pseudo-instruction, RegKill, which indicates that the value
in the register has been clobbered.
- Adjust regalloc to emit RegKills in the right places. Significantly,
this means that phis are mixed with StoreReg and RegKills after
regalloc.
- Track variable decomposition in ssa.LocalSlots.
- After the SSA backend is done, analyze the result and build location
lists for each LocalSlot.
- After assembly is done, update the location lists with the assembled
PC offsets, recompose variables, and build DWARF location lists. Emit the
list as a new linker symbol, one per function.
- In the linker, aggregate the location lists into a .debug_loc section.
TODO:
- currently disabled for non-X86/AMD64 because there are no data tables.
go build -toolexec 'toolstash -cmp' -a std succeeds.
With -dwarflocationlists false:
before: f02812195637909ff675782c0b46836a8ff01976
after: 06f61e8112a42ac34fb80e0c818b3cdb84a5e7ec
benchstat -geomean /tmp/220352263 /tmp/621364410
completed 15 of 15, estimated time remaining 0s (eta 3:52PM)
name old time/op new time/op delta
Template 199ms ± 3% 198ms ± 2% ~ (p=0.400 n=15+14)
Unicode 96.6ms ± 5% 96.4ms ± 5% ~ (p=0.838 n=15+15)
GoTypes 653ms ± 2% 647ms ± 2% ~ (p=0.102 n=15+14)
Flate 133ms ± 6% 129ms ± 3% -2.62% (p=0.041 n=15+15)
GoParser 164ms ± 5% 159ms ± 3% -3.05% (p=0.000 n=15+15)
Reflect 428ms ± 4% 422ms ± 3% ~ (p=0.156 n=15+13)
Tar 123ms ±10% 124ms ± 8% ~ (p=0.461 n=15+15)
XML 228ms ± 3% 224ms ± 3% -1.57% (p=0.045 n=15+15)
[Geo mean] 206ms 377ms +82.86%
name old user-time/op new user-time/op delta
Template 292ms ±10% 301ms ±12% ~ (p=0.189 n=15+15)
Unicode 166ms ±37% 158ms ±14% ~ (p=0.418 n=15+14)
GoTypes 962ms ± 6% 963ms ± 7% ~ (p=0.976 n=15+15)
Flate 207ms ±19% 200ms ±14% ~ (p=0.345 n=14+15)
GoParser 246ms ±22% 240ms ±15% ~ (p=0.587 n=15+15)
Reflect 611ms ±13% 587ms ±14% ~ (p=0.085 n=15+13)
Tar 211ms ±12% 217ms ±14% ~ (p=0.355 n=14+15)
XML 335ms ±15% 320ms ±18% ~ (p=0.169 n=15+15)
[Geo mean] 317ms 583ms +83.72%
name old alloc/op new alloc/op delta
Template 40.2MB ± 0% 40.2MB ± 0% -0.15% (p=0.000 n=14+15)
Unicode 29.2MB ± 0% 29.3MB ± 0% ~ (p=0.624 n=15+15)
GoTypes 114MB ± 0% 114MB ± 0% -0.15% (p=0.000 n=15+14)
Flate 25.7MB ± 0% 25.6MB ± 0% -0.18% (p=0.000 n=13+15)
GoParser 32.2MB ± 0% 32.2MB ± 0% -0.14% (p=0.003 n=15+15)
Reflect 77.8MB ± 0% 77.9MB ± 0% ~ (p=0.061 n=15+15)
Tar 27.1MB ± 0% 27.0MB ± 0% -0.11% (p=0.029 n=15+15)
XML 42.7MB ± 0% 42.5MB ± 0% -0.29% (p=0.000 n=15+15)
[Geo mean] 42.1MB 75.0MB +78.05%
name old allocs/op new allocs/op delta
Template 402k ± 1% 398k ± 0% -0.91% (p=0.000 n=15+15)
Unicode 344k ± 1% 344k ± 0% ~ (p=0.715 n=15+14)
GoTypes 1.18M ± 0% 1.17M ± 0% -0.91% (p=0.000 n=15+14)
Flate 243k ± 0% 240k ± 1% -1.05% (p=0.000 n=13+15)
GoParser 327k ± 1% 324k ± 1% -0.96% (p=0.000 n=15+15)
Reflect 984k ± 1% 982k ± 0% ~ (p=0.050 n=15+15)
Tar 261k ± 1% 259k ± 1% -0.77% (p=0.000 n=15+15)
XML 411k ± 0% 404k ± 1% -1.55% (p=0.000 n=15+15)
[Geo mean] 439k 755k +72.01%
name old text-bytes new text-bytes delta
HelloSize 694kB ± 0% 694kB ± 0% -0.00% (p=0.000 n=15+15)
name old data-bytes new data-bytes delta
HelloSize 5.55kB ± 0% 5.55kB ± 0% ~ (all equal)
name old bss-bytes new bss-bytes delta
HelloSize 133kB ± 0% 133kB ± 0% ~ (all equal)
name old exe-bytes new exe-bytes delta
HelloSize 1.04MB ± 0% 1.04MB ± 0% ~ (all equal)
Change-Id: I991fc553ef175db46bb23b2128317bbd48de70d8
Reviewed-on: https://go-review.googlesource.com/41770
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
2017-07-21 18:30:19 -04:00
|
|
|
Addstring(shstrtab, ".debug_loc")
|
2016-09-20 15:31:26 +12:00
|
|
|
Addstring(shstrtab, ".debug_line")
|
|
|
|
|
Addstring(shstrtab, ".debug_pubnames")
|
|
|
|
|
Addstring(shstrtab, ".debug_pubtypes")
|
|
|
|
|
Addstring(shstrtab, ".debug_gdb_scripts")
|
2017-05-02 16:46:01 +02:00
|
|
|
Addstring(shstrtab, ".debug_ranges")
|
2015-02-27 22:57:28 -05:00
|
|
|
if Linkmode == LinkExternal {
|
2016-09-20 15:31:26 +12:00
|
|
|
Addstring(shstrtab, elfRelType+".debug_info")
|
[dev.debug] cmd/compile: better DWARF with optimizations on
Debuggers use DWARF information to find local variables on the
stack and in registers. Prior to this CL, the DWARF information for
functions claimed that all variables were on the stack at all times.
That's incorrect when optimizations are enabled, and results in
debuggers showing data that is out of date or complete gibberish.
After this CL, the compiler is capable of representing variable
locations more accurately, and attempts to do so. Due to limitations of
the SSA backend, it's not possible to be completely correct.
There are a number of problems in the current design. One of the easier
to understand is that variable names currently must be attached to an
SSA value, but not all assignments in the source code actually result
in machine code. For example:
type myint int
var a int
b := myint(int)
and
b := (*uint64)(unsafe.Pointer(a))
don't generate machine code because the underlying representation is the
same, so the correct value of b will not be set when the user would
expect.
Generating the more precise debug information is behind a flag,
dwarflocationlists. Because of the issues described above, setting the
flag may not make the debugging experience much better, and may actually
make it worse in cases where the variable actually is on the stack and
the more complicated analysis doesn't realize it.
A number of changes are included:
- Add a new pseudo-instruction, RegKill, which indicates that the value
in the register has been clobbered.
- Adjust regalloc to emit RegKills in the right places. Significantly,
this means that phis are mixed with StoreReg and RegKills after
regalloc.
- Track variable decomposition in ssa.LocalSlots.
- After the SSA backend is done, analyze the result and build location
lists for each LocalSlot.
- After assembly is done, update the location lists with the assembled
PC offsets, recompose variables, and build DWARF location lists. Emit the
list as a new linker symbol, one per function.
- In the linker, aggregate the location lists into a .debug_loc section.
TODO:
- currently disabled for non-X86/AMD64 because there are no data tables.
go build -toolexec 'toolstash -cmp' -a std succeeds.
With -dwarflocationlists false:
before: f02812195637909ff675782c0b46836a8ff01976
after: 06f61e8112a42ac34fb80e0c818b3cdb84a5e7ec
benchstat -geomean /tmp/220352263 /tmp/621364410
completed 15 of 15, estimated time remaining 0s (eta 3:52PM)
name old time/op new time/op delta
Template 199ms ± 3% 198ms ± 2% ~ (p=0.400 n=15+14)
Unicode 96.6ms ± 5% 96.4ms ± 5% ~ (p=0.838 n=15+15)
GoTypes 653ms ± 2% 647ms ± 2% ~ (p=0.102 n=15+14)
Flate 133ms ± 6% 129ms ± 3% -2.62% (p=0.041 n=15+15)
GoParser 164ms ± 5% 159ms ± 3% -3.05% (p=0.000 n=15+15)
Reflect 428ms ± 4% 422ms ± 3% ~ (p=0.156 n=15+13)
Tar 123ms ±10% 124ms ± 8% ~ (p=0.461 n=15+15)
XML 228ms ± 3% 224ms ± 3% -1.57% (p=0.045 n=15+15)
[Geo mean] 206ms 377ms +82.86%
name old user-time/op new user-time/op delta
Template 292ms ±10% 301ms ±12% ~ (p=0.189 n=15+15)
Unicode 166ms ±37% 158ms ±14% ~ (p=0.418 n=15+14)
GoTypes 962ms ± 6% 963ms ± 7% ~ (p=0.976 n=15+15)
Flate 207ms ±19% 200ms ±14% ~ (p=0.345 n=14+15)
GoParser 246ms ±22% 240ms ±15% ~ (p=0.587 n=15+15)
Reflect 611ms ±13% 587ms ±14% ~ (p=0.085 n=15+13)
Tar 211ms ±12% 217ms ±14% ~ (p=0.355 n=14+15)
XML 335ms ±15% 320ms ±18% ~ (p=0.169 n=15+15)
[Geo mean] 317ms 583ms +83.72%
name old alloc/op new alloc/op delta
Template 40.2MB ± 0% 40.2MB ± 0% -0.15% (p=0.000 n=14+15)
Unicode 29.2MB ± 0% 29.3MB ± 0% ~ (p=0.624 n=15+15)
GoTypes 114MB ± 0% 114MB ± 0% -0.15% (p=0.000 n=15+14)
Flate 25.7MB ± 0% 25.6MB ± 0% -0.18% (p=0.000 n=13+15)
GoParser 32.2MB ± 0% 32.2MB ± 0% -0.14% (p=0.003 n=15+15)
Reflect 77.8MB ± 0% 77.9MB ± 0% ~ (p=0.061 n=15+15)
Tar 27.1MB ± 0% 27.0MB ± 0% -0.11% (p=0.029 n=15+15)
XML 42.7MB ± 0% 42.5MB ± 0% -0.29% (p=0.000 n=15+15)
[Geo mean] 42.1MB 75.0MB +78.05%
name old allocs/op new allocs/op delta
Template 402k ± 1% 398k ± 0% -0.91% (p=0.000 n=15+15)
Unicode 344k ± 1% 344k ± 0% ~ (p=0.715 n=15+14)
GoTypes 1.18M ± 0% 1.17M ± 0% -0.91% (p=0.000 n=15+14)
Flate 243k ± 0% 240k ± 1% -1.05% (p=0.000 n=13+15)
GoParser 327k ± 1% 324k ± 1% -0.96% (p=0.000 n=15+15)
Reflect 984k ± 1% 982k ± 0% ~ (p=0.050 n=15+15)
Tar 261k ± 1% 259k ± 1% -0.77% (p=0.000 n=15+15)
XML 411k ± 0% 404k ± 1% -1.55% (p=0.000 n=15+15)
[Geo mean] 439k 755k +72.01%
name old text-bytes new text-bytes delta
HelloSize 694kB ± 0% 694kB ± 0% -0.00% (p=0.000 n=15+15)
name old data-bytes new data-bytes delta
HelloSize 5.55kB ± 0% 5.55kB ± 0% ~ (all equal)
name old bss-bytes new bss-bytes delta
HelloSize 133kB ± 0% 133kB ± 0% ~ (all equal)
name old exe-bytes new exe-bytes delta
HelloSize 1.04MB ± 0% 1.04MB ± 0% ~ (all equal)
Change-Id: I991fc553ef175db46bb23b2128317bbd48de70d8
Reviewed-on: https://go-review.googlesource.com/41770
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
2017-07-21 18:30:19 -04:00
|
|
|
Addstring(shstrtab, elfRelType+".debug_loc")
|
2016-09-20 15:31:26 +12:00
|
|
|
Addstring(shstrtab, elfRelType+".debug_aranges")
|
|
|
|
|
Addstring(shstrtab, elfRelType+".debug_line")
|
|
|
|
|
Addstring(shstrtab, elfRelType+".debug_frame")
|
|
|
|
|
Addstring(shstrtab, elfRelType+".debug_pubnames")
|
|
|
|
|
Addstring(shstrtab, elfRelType+".debug_pubtypes")
|
2017-05-02 16:46:01 +02:00
|
|
|
Addstring(shstrtab, elfRelType+".debug_ranges")
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-14 09:23:04 -07:00
|
|
|
// Add section symbols for DWARF debug info. This is called before
|
2015-02-27 22:57:28 -05:00
|
|
|
// dwarfaddelfheaders.
|
2016-08-19 22:40:38 -04:00
|
|
|
func dwarfaddelfsectionsyms(ctxt *Link) {
|
2016-08-21 18:34:24 -04:00
|
|
|
if *FlagW { // disable dwarf
|
2015-02-27 22:57:28 -05:00
|
|
|
return
|
|
|
|
|
}
|
2015-04-08 12:55:34 -07:00
|
|
|
if Linkmode != LinkExternal {
|
2016-03-14 09:23:04 -07:00
|
|
|
return
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
sym := ctxt.Syms.Lookup(".debug_info", 0)
|
2016-03-14 09:23:04 -07:00
|
|
|
putelfsectionsym(sym, sym.Sect.Elfsect.shnum)
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
sym = ctxt.Syms.Lookup(".debug_abbrev", 0)
|
2016-03-14 09:23:04 -07:00
|
|
|
putelfsectionsym(sym, sym.Sect.Elfsect.shnum)
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
sym = ctxt.Syms.Lookup(".debug_line", 0)
|
2016-03-14 09:23:04 -07:00
|
|
|
putelfsectionsym(sym, sym.Sect.Elfsect.shnum)
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
sym = ctxt.Syms.Lookup(".debug_frame", 0)
|
2016-03-14 09:23:04 -07:00
|
|
|
putelfsectionsym(sym, sym.Sect.Elfsect.shnum)
|
[dev.debug] cmd/compile: better DWARF with optimizations on
Debuggers use DWARF information to find local variables on the
stack and in registers. Prior to this CL, the DWARF information for
functions claimed that all variables were on the stack at all times.
That's incorrect when optimizations are enabled, and results in
debuggers showing data that is out of date or complete gibberish.
After this CL, the compiler is capable of representing variable
locations more accurately, and attempts to do so. Due to limitations of
the SSA backend, it's not possible to be completely correct.
There are a number of problems in the current design. One of the easier
to understand is that variable names currently must be attached to an
SSA value, but not all assignments in the source code actually result
in machine code. For example:
type myint int
var a int
b := myint(int)
and
b := (*uint64)(unsafe.Pointer(a))
don't generate machine code because the underlying representation is the
same, so the correct value of b will not be set when the user would
expect.
Generating the more precise debug information is behind a flag,
dwarflocationlists. Because of the issues described above, setting the
flag may not make the debugging experience much better, and may actually
make it worse in cases where the variable actually is on the stack and
the more complicated analysis doesn't realize it.
A number of changes are included:
- Add a new pseudo-instruction, RegKill, which indicates that the value
in the register has been clobbered.
- Adjust regalloc to emit RegKills in the right places. Significantly,
this means that phis are mixed with StoreReg and RegKills after
regalloc.
- Track variable decomposition in ssa.LocalSlots.
- After the SSA backend is done, analyze the result and build location
lists for each LocalSlot.
- After assembly is done, update the location lists with the assembled
PC offsets, recompose variables, and build DWARF location lists. Emit the
list as a new linker symbol, one per function.
- In the linker, aggregate the location lists into a .debug_loc section.
TODO:
- currently disabled for non-X86/AMD64 because there are no data tables.
go build -toolexec 'toolstash -cmp' -a std succeeds.
With -dwarflocationlists false:
before: f02812195637909ff675782c0b46836a8ff01976
after: 06f61e8112a42ac34fb80e0c818b3cdb84a5e7ec
benchstat -geomean /tmp/220352263 /tmp/621364410
completed 15 of 15, estimated time remaining 0s (eta 3:52PM)
name old time/op new time/op delta
Template 199ms ± 3% 198ms ± 2% ~ (p=0.400 n=15+14)
Unicode 96.6ms ± 5% 96.4ms ± 5% ~ (p=0.838 n=15+15)
GoTypes 653ms ± 2% 647ms ± 2% ~ (p=0.102 n=15+14)
Flate 133ms ± 6% 129ms ± 3% -2.62% (p=0.041 n=15+15)
GoParser 164ms ± 5% 159ms ± 3% -3.05% (p=0.000 n=15+15)
Reflect 428ms ± 4% 422ms ± 3% ~ (p=0.156 n=15+13)
Tar 123ms ±10% 124ms ± 8% ~ (p=0.461 n=15+15)
XML 228ms ± 3% 224ms ± 3% -1.57% (p=0.045 n=15+15)
[Geo mean] 206ms 377ms +82.86%
name old user-time/op new user-time/op delta
Template 292ms ±10% 301ms ±12% ~ (p=0.189 n=15+15)
Unicode 166ms ±37% 158ms ±14% ~ (p=0.418 n=15+14)
GoTypes 962ms ± 6% 963ms ± 7% ~ (p=0.976 n=15+15)
Flate 207ms ±19% 200ms ±14% ~ (p=0.345 n=14+15)
GoParser 246ms ±22% 240ms ±15% ~ (p=0.587 n=15+15)
Reflect 611ms ±13% 587ms ±14% ~ (p=0.085 n=15+13)
Tar 211ms ±12% 217ms ±14% ~ (p=0.355 n=14+15)
XML 335ms ±15% 320ms ±18% ~ (p=0.169 n=15+15)
[Geo mean] 317ms 583ms +83.72%
name old alloc/op new alloc/op delta
Template 40.2MB ± 0% 40.2MB ± 0% -0.15% (p=0.000 n=14+15)
Unicode 29.2MB ± 0% 29.3MB ± 0% ~ (p=0.624 n=15+15)
GoTypes 114MB ± 0% 114MB ± 0% -0.15% (p=0.000 n=15+14)
Flate 25.7MB ± 0% 25.6MB ± 0% -0.18% (p=0.000 n=13+15)
GoParser 32.2MB ± 0% 32.2MB ± 0% -0.14% (p=0.003 n=15+15)
Reflect 77.8MB ± 0% 77.9MB ± 0% ~ (p=0.061 n=15+15)
Tar 27.1MB ± 0% 27.0MB ± 0% -0.11% (p=0.029 n=15+15)
XML 42.7MB ± 0% 42.5MB ± 0% -0.29% (p=0.000 n=15+15)
[Geo mean] 42.1MB 75.0MB +78.05%
name old allocs/op new allocs/op delta
Template 402k ± 1% 398k ± 0% -0.91% (p=0.000 n=15+15)
Unicode 344k ± 1% 344k ± 0% ~ (p=0.715 n=15+14)
GoTypes 1.18M ± 0% 1.17M ± 0% -0.91% (p=0.000 n=15+14)
Flate 243k ± 0% 240k ± 1% -1.05% (p=0.000 n=13+15)
GoParser 327k ± 1% 324k ± 1% -0.96% (p=0.000 n=15+15)
Reflect 984k ± 1% 982k ± 0% ~ (p=0.050 n=15+15)
Tar 261k ± 1% 259k ± 1% -0.77% (p=0.000 n=15+15)
XML 411k ± 0% 404k ± 1% -1.55% (p=0.000 n=15+15)
[Geo mean] 439k 755k +72.01%
name old text-bytes new text-bytes delta
HelloSize 694kB ± 0% 694kB ± 0% -0.00% (p=0.000 n=15+15)
name old data-bytes new data-bytes delta
HelloSize 5.55kB ± 0% 5.55kB ± 0% ~ (all equal)
name old bss-bytes new bss-bytes delta
HelloSize 133kB ± 0% 133kB ± 0% ~ (all equal)
name old exe-bytes new exe-bytes delta
HelloSize 1.04MB ± 0% 1.04MB ± 0% ~ (all equal)
Change-Id: I991fc553ef175db46bb23b2128317bbd48de70d8
Reviewed-on: https://go-review.googlesource.com/41770
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
2017-07-21 18:30:19 -04:00
|
|
|
sym = ctxt.Syms.Lookup(".debug_loc", 0)
|
|
|
|
|
if sym.Sect != nil {
|
|
|
|
|
putelfsectionsym(sym, sym.Sect.Elfsect.shnum)
|
|
|
|
|
}
|
2017-05-02 16:46:01 +02:00
|
|
|
sym = ctxt.Syms.Lookup(".debug_ranges", 0)
|
|
|
|
|
if sym.Sect != nil {
|
|
|
|
|
putelfsectionsym(sym, sym.Sect.Elfsect.shnum)
|
|
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|