mirror of
https://github.com/golang/go
synced 2024-11-19 15:14:45 -07:00
cmd/compile,cmd/link: export int global consts to DWARF
Updates #14517 Change-Id: I23ef88e71c89da12dffcadf5562ea2d7557b62cf Reviewed-on: https://go-review.googlesource.com/61019 Reviewed-by: Austin Clements <austin@google.com> Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
f366379d84
commit
9daee93121
@ -203,24 +203,57 @@ func addptabs() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func dumpGlobal(n *Node) {
|
||||||
|
if n.Type == nil {
|
||||||
|
Fatalf("external %v nil type\n", n)
|
||||||
|
}
|
||||||
|
if n.Class() == PFUNC {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if n.Sym.Pkg != localpkg {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dowidth(n.Type)
|
||||||
|
ggloblnod(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func dumpGlobalConst(n *Node) {
|
||||||
|
// only export typed constants
|
||||||
|
if n.Type == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if n.Sym.Pkg != localpkg {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// only export integer constants for now
|
||||||
|
switch n.Type.Etype {
|
||||||
|
case TINT8:
|
||||||
|
case TINT16:
|
||||||
|
case TINT32:
|
||||||
|
case TINT64:
|
||||||
|
case TINT:
|
||||||
|
case TUINT8:
|
||||||
|
case TUINT16:
|
||||||
|
case TUINT32:
|
||||||
|
case TUINT64:
|
||||||
|
case TUINT:
|
||||||
|
case TUINTPTR:
|
||||||
|
// ok
|
||||||
|
default:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Ctxt.DwarfIntConst(myimportpath, n.Sym.Name, typesymname(n.Type), n.Int64())
|
||||||
|
}
|
||||||
|
|
||||||
func dumpglobls() {
|
func dumpglobls() {
|
||||||
// add globals
|
// add globals
|
||||||
for _, n := range externdcl {
|
for _, n := range externdcl {
|
||||||
if n.Op != ONAME {
|
switch n.Op {
|
||||||
continue
|
case ONAME:
|
||||||
|
dumpGlobal(n)
|
||||||
|
case OLITERAL:
|
||||||
|
dumpGlobalConst(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.Type == nil {
|
|
||||||
Fatalf("external %v nil type\n", n)
|
|
||||||
}
|
|
||||||
if n.Class() == PFUNC {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if n.Sym.Pkg != localpkg {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
dowidth(n.Type)
|
|
||||||
ggloblnod(n)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
obj.SortSlice(funcsyms, func(i, j int) bool {
|
obj.SortSlice(funcsyms, func(i, j int) bool {
|
||||||
|
2
src/cmd/dist/build.go
vendored
2
src/cmd/dist/build.go
vendored
@ -685,7 +685,7 @@ func install(dir string) {
|
|||||||
// For package runtime, this writes go_asm.h, which
|
// For package runtime, this writes go_asm.h, which
|
||||||
// the assembly files will need.
|
// the assembly files will need.
|
||||||
pkg := dir
|
pkg := dir
|
||||||
if strings.HasPrefix(dir, "cmd/") {
|
if strings.HasPrefix(dir, "cmd/") && strings.Count(dir, "/") == 1 {
|
||||||
pkg = "main"
|
pkg = "main"
|
||||||
}
|
}
|
||||||
b := pathf("%s/_go_.a", workdir)
|
b := pathf("%s/_go_.a", workdir)
|
||||||
|
@ -21,6 +21,10 @@ const LocPrefix = "go.loc."
|
|||||||
// RangePrefix is the prefix for all the symbols containing DWARF range lists.
|
// RangePrefix is the prefix for all the symbols containing DWARF range lists.
|
||||||
const RangePrefix = "go.range."
|
const RangePrefix = "go.range."
|
||||||
|
|
||||||
|
// InfoConstPrefix is the prefix for all symbols containing DWARF info
|
||||||
|
// entries that contain constants.
|
||||||
|
const ConstInfoPrefix = "go.constinfo."
|
||||||
|
|
||||||
// Sym represents a symbol.
|
// Sym represents a symbol.
|
||||||
type Sym interface {
|
type Sym interface {
|
||||||
Len() int64
|
Len() int64
|
||||||
@ -234,6 +238,7 @@ const (
|
|||||||
DW_ABRV_COMPUNIT
|
DW_ABRV_COMPUNIT
|
||||||
DW_ABRV_FUNCTION
|
DW_ABRV_FUNCTION
|
||||||
DW_ABRV_VARIABLE
|
DW_ABRV_VARIABLE
|
||||||
|
DW_ABRV_INT_CONSTANT
|
||||||
DW_ABRV_AUTO
|
DW_ABRV_AUTO
|
||||||
DW_ABRV_AUTO_LOCLIST
|
DW_ABRV_AUTO_LOCLIST
|
||||||
DW_ABRV_PARAM
|
DW_ABRV_PARAM
|
||||||
@ -310,6 +315,17 @@ var abbrevs = [DW_NABRV]dwAbbrev{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/* INT CONSTANT */
|
||||||
|
{
|
||||||
|
DW_TAG_constant,
|
||||||
|
DW_CHILDREN_no,
|
||||||
|
[]dwAttrForm{
|
||||||
|
{DW_AT_name, DW_FORM_string},
|
||||||
|
{DW_AT_type, DW_FORM_ref_addr},
|
||||||
|
{DW_AT_const_value, DW_FORM_sdata},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
/* AUTO */
|
/* AUTO */
|
||||||
{
|
{
|
||||||
DW_TAG_variable,
|
DW_TAG_variable,
|
||||||
@ -734,6 +750,14 @@ func HasChildren(die *DWDie) bool {
|
|||||||
return abbrevs[die.Abbrev].children != 0
|
return abbrevs[die.Abbrev].children != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PutIntConst writes a DIE for an integer constant
|
||||||
|
func PutIntConst(ctxt Context, info, typ Sym, name string, val int64) {
|
||||||
|
Uleb128put(ctxt, info, DW_ABRV_INT_CONSTANT)
|
||||||
|
putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
|
||||||
|
putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, typ)
|
||||||
|
putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_sdata, DW_CLS_CONSTANT, val, nil)
|
||||||
|
}
|
||||||
|
|
||||||
// PutFunc writes a DIE for a function to s.
|
// PutFunc writes a DIE for a function to s.
|
||||||
// It also writes child DIEs for each variable in vars.
|
// It also writes child DIEs for each variable in vars.
|
||||||
func PutFunc(ctxt Context, info, loc, ranges Sym, name string, external bool, startPC Sym, size int64, scopes []Scope) error {
|
func PutFunc(ctxt Context, info, loc, ranges Sym, name string, external bool, startPC Sym, size int64, scopes []Scope) error {
|
||||||
|
@ -499,3 +499,16 @@ func (ctxt *Link) populateDWARF(curfn interface{}, s *LSym) {
|
|||||||
ctxt.Diag("emitting DWARF for %s failed: %v", s.Name, err)
|
ctxt.Diag("emitting DWARF for %s failed: %v", s.Name, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DwarfIntConst creates a link symbol for an integer constant with the
|
||||||
|
// given name, type and value.
|
||||||
|
func (ctxt *Link) DwarfIntConst(myimportpath, name, typename string, val int64) {
|
||||||
|
if myimportpath == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s := ctxt.LookupInit(dwarf.ConstInfoPrefix+myimportpath, func(s *LSym) {
|
||||||
|
s.Type = objabi.SDWARFINFO
|
||||||
|
ctxt.Data = append(ctxt.Data, s)
|
||||||
|
})
|
||||||
|
dwarf.PutIntConst(dwCtxt{ctxt}, s, ctxt.Lookup(dwarf.InfoPrefix+typename), myimportpath+"."+name, val)
|
||||||
|
}
|
||||||
|
@ -972,6 +972,21 @@ func getCompilationDir() string {
|
|||||||
return "/"
|
return "/"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func importInfoSymbol(ctxt *Link, dsym *Symbol) {
|
||||||
|
dsym.Attr |= AttrNotInSymbolTable | AttrReachable
|
||||||
|
dsym.Type = SDWARFINFO
|
||||||
|
for _, r := range dsym.R {
|
||||||
|
if r.Type == objabi.R_DWARFREF && r.Sym.Size == 0 {
|
||||||
|
if Buildmode == BuildmodeShared {
|
||||||
|
// These type symbols may not be present in BuildmodeShared. Skip.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
n := nameFromDIESym(r.Sym)
|
||||||
|
defgotype(ctxt, ctxt.Syms.Lookup("type."+n, 0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func writelines(ctxt *Link, syms []*Symbol) ([]*Symbol, []*Symbol) {
|
func writelines(ctxt *Link, syms []*Symbol) ([]*Symbol, []*Symbol) {
|
||||||
var dwarfctxt dwarf.Context = dwctxt{ctxt}
|
var dwarfctxt dwarf.Context = dwctxt{ctxt}
|
||||||
ls := ctxt.Syms.Lookup(".debug_line", 0)
|
ls := ctxt.Syms.Lookup(".debug_line", 0)
|
||||||
@ -1064,18 +1079,7 @@ func writelines(ctxt *Link, syms []*Symbol) ([]*Symbol, []*Symbol) {
|
|||||||
epcs = s
|
epcs = s
|
||||||
|
|
||||||
dsym := ctxt.Syms.Lookup(dwarf.InfoPrefix+s.Name, int(s.Version))
|
dsym := ctxt.Syms.Lookup(dwarf.InfoPrefix+s.Name, int(s.Version))
|
||||||
dsym.Attr |= AttrNotInSymbolTable | AttrReachable
|
importInfoSymbol(ctxt, dsym)
|
||||||
dsym.Type = SDWARFINFO
|
|
||||||
for _, r := range dsym.R {
|
|
||||||
if r.Type == objabi.R_DWARFREF && r.Sym.Size == 0 {
|
|
||||||
if Buildmode == BuildmodeShared {
|
|
||||||
// These type symbols may not be present in BuildmodeShared. Skip.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
n := nameFromDIESym(r.Sym)
|
|
||||||
defgotype(ctxt, ctxt.Syms.Lookup("type."+n, 0))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
funcs = append(funcs, dsym)
|
funcs = append(funcs, dsym)
|
||||||
|
|
||||||
finddebugruntimepath(s)
|
finddebugruntimepath(s)
|
||||||
@ -1296,7 +1300,7 @@ const (
|
|||||||
COMPUNITHEADERSIZE = 4 + 2 + 4 + 1
|
COMPUNITHEADERSIZE = 4 + 2 + 4 + 1
|
||||||
)
|
)
|
||||||
|
|
||||||
func writeinfo(ctxt *Link, syms []*Symbol, funcs []*Symbol, abbrevsym *Symbol) []*Symbol {
|
func writeinfo(ctxt *Link, syms []*Symbol, funcs, consts []*Symbol, abbrevsym *Symbol) []*Symbol {
|
||||||
infosec := ctxt.Syms.Lookup(".debug_info", 0)
|
infosec := ctxt.Syms.Lookup(".debug_info", 0)
|
||||||
infosec.R = infosec.R[:0]
|
infosec.R = infosec.R[:0]
|
||||||
infosec.Type = SDWARFINFO
|
infosec.Type = SDWARFINFO
|
||||||
@ -1330,6 +1334,10 @@ func writeinfo(ctxt *Link, syms []*Symbol, funcs []*Symbol, abbrevsym *Symbol) [
|
|||||||
cu = append(cu, funcs...)
|
cu = append(cu, funcs...)
|
||||||
funcs = nil
|
funcs = nil
|
||||||
}
|
}
|
||||||
|
if consts != nil {
|
||||||
|
cu = append(cu, consts...)
|
||||||
|
consts = nil
|
||||||
|
}
|
||||||
cu = putdies(ctxt, dwarfctxt, cu, compunit.Child)
|
cu = putdies(ctxt, dwarfctxt, cu, compunit.Child)
|
||||||
var cusize int64
|
var cusize int64
|
||||||
for _, child := range cu {
|
for _, child := range cu {
|
||||||
@ -1544,6 +1552,14 @@ func dwarfgeneratedebugsyms(ctxt *Link) {
|
|||||||
|
|
||||||
genasmsym(ctxt, defdwsymb)
|
genasmsym(ctxt, defdwsymb)
|
||||||
|
|
||||||
|
var consts []*Symbol
|
||||||
|
for _, lib := range ctxt.Library {
|
||||||
|
if s := ctxt.Syms.Lookup(dwarf.ConstInfoPrefix+lib.Pkg, 0); s != nil {
|
||||||
|
importInfoSymbol(ctxt, s)
|
||||||
|
consts = append(consts, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
abbrev := writeabbrev(ctxt)
|
abbrev := writeabbrev(ctxt)
|
||||||
syms := []*Symbol{abbrev}
|
syms := []*Symbol{abbrev}
|
||||||
syms, funcs := writelines(ctxt, syms)
|
syms, funcs := writelines(ctxt, syms)
|
||||||
@ -1563,7 +1579,7 @@ func dwarfgeneratedebugsyms(ctxt *Link) {
|
|||||||
|
|
||||||
// Need to reorder symbols so SDWARFINFO is after all SDWARFSECT
|
// Need to reorder symbols so SDWARFINFO is after all SDWARFSECT
|
||||||
// (but we need to generate dies before writepub)
|
// (but we need to generate dies before writepub)
|
||||||
infosyms := writeinfo(ctxt, nil, funcs, abbrev)
|
infosyms := writeinfo(ctxt, nil, funcs, consts, abbrev)
|
||||||
|
|
||||||
syms = writepub(ctxt, ".debug_pubnames", ispubname, syms)
|
syms = writepub(ctxt, ".debug_pubnames", ispubname, syms)
|
||||||
syms = writepub(ctxt, ".debug_pubtypes", ispubtype, syms)
|
syms = writepub(ctxt, ".debug_pubtypes", ispubtype, syms)
|
||||||
|
@ -381,3 +381,61 @@ func TestGdbAutotmpTypes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const constsSource = `
|
||||||
|
package main
|
||||||
|
|
||||||
|
const aConstant int = 42
|
||||||
|
const largeConstant uint64 = ^uint64(0)
|
||||||
|
const minusOne int64 = -1
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
println("hello world")
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
func TestGdbConst(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
checkGdbEnvironment(t)
|
||||||
|
checkGdbVersion(t)
|
||||||
|
|
||||||
|
dir, err := ioutil.TempDir("", "go-build")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create temp directory: %v", err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
// Build the source code.
|
||||||
|
src := filepath.Join(dir, "main.go")
|
||||||
|
err = ioutil.WriteFile(src, []byte(constsSource), 0644)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create file: %v", err)
|
||||||
|
}
|
||||||
|
cmd := exec.Command(testenv.GoToolPath(t), "build", "-gcflags=-N -l", "-o", "a.exe")
|
||||||
|
cmd.Dir = dir
|
||||||
|
out, err := testenv.CleanCmdEnv(cmd).CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("building source %v\n%s", err, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute gdb commands.
|
||||||
|
args := []string{"-nx", "-batch",
|
||||||
|
"-ex", "set startup-with-shell off",
|
||||||
|
"-ex", "break main.main",
|
||||||
|
"-ex", "run",
|
||||||
|
"-ex", "print main.aConstant",
|
||||||
|
"-ex", "print main.largeConstant",
|
||||||
|
"-ex", "print main.minusOne",
|
||||||
|
"-ex", "print 'runtime._MSpanInUse'",
|
||||||
|
filepath.Join(dir, "a.exe"),
|
||||||
|
}
|
||||||
|
got, _ := exec.Command("gdb", args...).CombinedOutput()
|
||||||
|
|
||||||
|
sgot := string(got)
|
||||||
|
|
||||||
|
t.Logf("output %q", sgot)
|
||||||
|
|
||||||
|
if strings.Index(sgot, "\n$1 = 42\n$2 = 18446744073709551615\n$3 = -1\n$4 = 1 '\\001'") < 0 {
|
||||||
|
t.Fatalf("output mismatch")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user