Skip to content

Commit 9daee93

Browse files
aarzilliaclements
authored andcommitted
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 <[email protected]> Run-TryBot: Austin Clements <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent f366379 commit 9daee93

File tree

6 files changed

+173
-29
lines changed

6 files changed

+173
-29
lines changed

src/cmd/compile/internal/gc/obj.go

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -203,24 +203,57 @@ func addptabs() {
203203
}
204204
}
205205

206+
func dumpGlobal(n *Node) {
207+
if n.Type == nil {
208+
Fatalf("external %v nil type\n", n)
209+
}
210+
if n.Class() == PFUNC {
211+
return
212+
}
213+
if n.Sym.Pkg != localpkg {
214+
return
215+
}
216+
dowidth(n.Type)
217+
ggloblnod(n)
218+
}
219+
220+
func dumpGlobalConst(n *Node) {
221+
// only export typed constants
222+
if n.Type == nil {
223+
return
224+
}
225+
if n.Sym.Pkg != localpkg {
226+
return
227+
}
228+
// only export integer constants for now
229+
switch n.Type.Etype {
230+
case TINT8:
231+
case TINT16:
232+
case TINT32:
233+
case TINT64:
234+
case TINT:
235+
case TUINT8:
236+
case TUINT16:
237+
case TUINT32:
238+
case TUINT64:
239+
case TUINT:
240+
case TUINTPTR:
241+
// ok
242+
default:
243+
return
244+
}
245+
Ctxt.DwarfIntConst(myimportpath, n.Sym.Name, typesymname(n.Type), n.Int64())
246+
}
247+
206248
func dumpglobls() {
207249
// add globals
208250
for _, n := range externdcl {
209-
if n.Op != ONAME {
210-
continue
211-
}
212-
213-
if n.Type == nil {
214-
Fatalf("external %v nil type\n", n)
215-
}
216-
if n.Class() == PFUNC {
217-
continue
218-
}
219-
if n.Sym.Pkg != localpkg {
220-
continue
251+
switch n.Op {
252+
case ONAME:
253+
dumpGlobal(n)
254+
case OLITERAL:
255+
dumpGlobalConst(n)
221256
}
222-
dowidth(n.Type)
223-
ggloblnod(n)
224257
}
225258

226259
obj.SortSlice(funcsyms, func(i, j int) bool {

src/cmd/dist/build.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,7 @@ func install(dir string) {
685685
// For package runtime, this writes go_asm.h, which
686686
// the assembly files will need.
687687
pkg := dir
688-
if strings.HasPrefix(dir, "cmd/") {
688+
if strings.HasPrefix(dir, "cmd/") && strings.Count(dir, "/") == 1 {
689689
pkg = "main"
690690
}
691691
b := pathf("%s/_go_.a", workdir)

src/cmd/internal/dwarf/dwarf.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ const LocPrefix = "go.loc."
2121
// RangePrefix is the prefix for all the symbols containing DWARF range lists.
2222
const RangePrefix = "go.range."
2323

24+
// InfoConstPrefix is the prefix for all symbols containing DWARF info
25+
// entries that contain constants.
26+
const ConstInfoPrefix = "go.constinfo."
27+
2428
// Sym represents a symbol.
2529
type Sym interface {
2630
Len() int64
@@ -234,6 +238,7 @@ const (
234238
DW_ABRV_COMPUNIT
235239
DW_ABRV_FUNCTION
236240
DW_ABRV_VARIABLE
241+
DW_ABRV_INT_CONSTANT
237242
DW_ABRV_AUTO
238243
DW_ABRV_AUTO_LOCLIST
239244
DW_ABRV_PARAM
@@ -310,6 +315,17 @@ var abbrevs = [DW_NABRV]dwAbbrev{
310315
},
311316
},
312317

318+
/* INT CONSTANT */
319+
{
320+
DW_TAG_constant,
321+
DW_CHILDREN_no,
322+
[]dwAttrForm{
323+
{DW_AT_name, DW_FORM_string},
324+
{DW_AT_type, DW_FORM_ref_addr},
325+
{DW_AT_const_value, DW_FORM_sdata},
326+
},
327+
},
328+
313329
/* AUTO */
314330
{
315331
DW_TAG_variable,
@@ -734,6 +750,14 @@ func HasChildren(die *DWDie) bool {
734750
return abbrevs[die.Abbrev].children != 0
735751
}
736752

753+
// PutIntConst writes a DIE for an integer constant
754+
func PutIntConst(ctxt Context, info, typ Sym, name string, val int64) {
755+
Uleb128put(ctxt, info, DW_ABRV_INT_CONSTANT)
756+
putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
757+
putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, typ)
758+
putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_sdata, DW_CLS_CONSTANT, val, nil)
759+
}
760+
737761
// PutFunc writes a DIE for a function to s.
738762
// It also writes child DIEs for each variable in vars.
739763
func PutFunc(ctxt Context, info, loc, ranges Sym, name string, external bool, startPC Sym, size int64, scopes []Scope) error {

src/cmd/internal/obj/objfile.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,3 +499,16 @@ func (ctxt *Link) populateDWARF(curfn interface{}, s *LSym) {
499499
ctxt.Diag("emitting DWARF for %s failed: %v", s.Name, err)
500500
}
501501
}
502+
503+
// DwarfIntConst creates a link symbol for an integer constant with the
504+
// given name, type and value.
505+
func (ctxt *Link) DwarfIntConst(myimportpath, name, typename string, val int64) {
506+
if myimportpath == "" {
507+
return
508+
}
509+
s := ctxt.LookupInit(dwarf.ConstInfoPrefix+myimportpath, func(s *LSym) {
510+
s.Type = objabi.SDWARFINFO
511+
ctxt.Data = append(ctxt.Data, s)
512+
})
513+
dwarf.PutIntConst(dwCtxt{ctxt}, s, ctxt.Lookup(dwarf.InfoPrefix+typename), myimportpath+"."+name, val)
514+
}

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

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -972,6 +972,21 @@ func getCompilationDir() string {
972972
return "/"
973973
}
974974

975+
func importInfoSymbol(ctxt *Link, dsym *Symbol) {
976+
dsym.Attr |= AttrNotInSymbolTable | AttrReachable
977+
dsym.Type = SDWARFINFO
978+
for _, r := range dsym.R {
979+
if r.Type == objabi.R_DWARFREF && r.Sym.Size == 0 {
980+
if Buildmode == BuildmodeShared {
981+
// These type symbols may not be present in BuildmodeShared. Skip.
982+
continue
983+
}
984+
n := nameFromDIESym(r.Sym)
985+
defgotype(ctxt, ctxt.Syms.Lookup("type."+n, 0))
986+
}
987+
}
988+
}
989+
975990
func writelines(ctxt *Link, syms []*Symbol) ([]*Symbol, []*Symbol) {
976991
var dwarfctxt dwarf.Context = dwctxt{ctxt}
977992
ls := ctxt.Syms.Lookup(".debug_line", 0)
@@ -1064,18 +1079,7 @@ func writelines(ctxt *Link, syms []*Symbol) ([]*Symbol, []*Symbol) {
10641079
epcs = s
10651080

10661081
dsym := ctxt.Syms.Lookup(dwarf.InfoPrefix+s.Name, int(s.Version))
1067-
dsym.Attr |= AttrNotInSymbolTable | AttrReachable
1068-
dsym.Type = SDWARFINFO
1069-
for _, r := range dsym.R {
1070-
if r.Type == objabi.R_DWARFREF && r.Sym.Size == 0 {
1071-
if Buildmode == BuildmodeShared {
1072-
// These type symbols may not be present in BuildmodeShared. Skip.
1073-
continue
1074-
}
1075-
n := nameFromDIESym(r.Sym)
1076-
defgotype(ctxt, ctxt.Syms.Lookup("type."+n, 0))
1077-
}
1078-
}
1082+
importInfoSymbol(ctxt, dsym)
10791083
funcs = append(funcs, dsym)
10801084

10811085
finddebugruntimepath(s)
@@ -1296,7 +1300,7 @@ const (
12961300
COMPUNITHEADERSIZE = 4 + 2 + 4 + 1
12971301
)
12981302

1299-
func writeinfo(ctxt *Link, syms []*Symbol, funcs []*Symbol, abbrevsym *Symbol) []*Symbol {
1303+
func writeinfo(ctxt *Link, syms []*Symbol, funcs, consts []*Symbol, abbrevsym *Symbol) []*Symbol {
13001304
infosec := ctxt.Syms.Lookup(".debug_info", 0)
13011305
infosec.R = infosec.R[:0]
13021306
infosec.Type = SDWARFINFO
@@ -1330,6 +1334,10 @@ func writeinfo(ctxt *Link, syms []*Symbol, funcs []*Symbol, abbrevsym *Symbol) [
13301334
cu = append(cu, funcs...)
13311335
funcs = nil
13321336
}
1337+
if consts != nil {
1338+
cu = append(cu, consts...)
1339+
consts = nil
1340+
}
13331341
cu = putdies(ctxt, dwarfctxt, cu, compunit.Child)
13341342
var cusize int64
13351343
for _, child := range cu {
@@ -1544,6 +1552,14 @@ func dwarfgeneratedebugsyms(ctxt *Link) {
15441552

15451553
genasmsym(ctxt, defdwsymb)
15461554

1555+
var consts []*Symbol
1556+
for _, lib := range ctxt.Library {
1557+
if s := ctxt.Syms.Lookup(dwarf.ConstInfoPrefix+lib.Pkg, 0); s != nil {
1558+
importInfoSymbol(ctxt, s)
1559+
consts = append(consts, s)
1560+
}
1561+
}
1562+
15471563
abbrev := writeabbrev(ctxt)
15481564
syms := []*Symbol{abbrev}
15491565
syms, funcs := writelines(ctxt, syms)
@@ -1563,7 +1579,7 @@ func dwarfgeneratedebugsyms(ctxt *Link) {
15631579

15641580
// Need to reorder symbols so SDWARFINFO is after all SDWARFSECT
15651581
// (but we need to generate dies before writepub)
1566-
infosyms := writeinfo(ctxt, nil, funcs, abbrev)
1582+
infosyms := writeinfo(ctxt, nil, funcs, consts, abbrev)
15671583

15681584
syms = writepub(ctxt, ".debug_pubnames", ispubname, syms)
15691585
syms = writepub(ctxt, ".debug_pubtypes", ispubtype, syms)

src/runtime/runtime-gdb_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,3 +381,61 @@ func TestGdbAutotmpTypes(t *testing.T) {
381381
}
382382
}
383383
}
384+
385+
const constsSource = `
386+
package main
387+
388+
const aConstant int = 42
389+
const largeConstant uint64 = ^uint64(0)
390+
const minusOne int64 = -1
391+
392+
func main() {
393+
println("hello world")
394+
}
395+
`
396+
397+
func TestGdbConst(t *testing.T) {
398+
t.Parallel()
399+
checkGdbEnvironment(t)
400+
checkGdbVersion(t)
401+
402+
dir, err := ioutil.TempDir("", "go-build")
403+
if err != nil {
404+
t.Fatalf("failed to create temp directory: %v", err)
405+
}
406+
defer os.RemoveAll(dir)
407+
408+
// Build the source code.
409+
src := filepath.Join(dir, "main.go")
410+
err = ioutil.WriteFile(src, []byte(constsSource), 0644)
411+
if err != nil {
412+
t.Fatalf("failed to create file: %v", err)
413+
}
414+
cmd := exec.Command(testenv.GoToolPath(t), "build", "-gcflags=-N -l", "-o", "a.exe")
415+
cmd.Dir = dir
416+
out, err := testenv.CleanCmdEnv(cmd).CombinedOutput()
417+
if err != nil {
418+
t.Fatalf("building source %v\n%s", err, out)
419+
}
420+
421+
// Execute gdb commands.
422+
args := []string{"-nx", "-batch",
423+
"-ex", "set startup-with-shell off",
424+
"-ex", "break main.main",
425+
"-ex", "run",
426+
"-ex", "print main.aConstant",
427+
"-ex", "print main.largeConstant",
428+
"-ex", "print main.minusOne",
429+
"-ex", "print 'runtime._MSpanInUse'",
430+
filepath.Join(dir, "a.exe"),
431+
}
432+
got, _ := exec.Command("gdb", args...).CombinedOutput()
433+
434+
sgot := string(got)
435+
436+
t.Logf("output %q", sgot)
437+
438+
if strings.Index(sgot, "\n$1 = 42\n$2 = 18446744073709551615\n$3 = -1\n$4 = 1 '\\001'") < 0 {
439+
t.Fatalf("output mismatch")
440+
}
441+
}

0 commit comments

Comments
 (0)