Skip to content

Commit 2c1d2e0

Browse files
committed
cmd/compile, cmd/link: record compiler flags in DW_AT_producer
This adds a whitelisted subset of compiler flags to the DW_AT_producer DWARF attribute of each package compilation unit DIE. This is common practice in DWARF and can help debuggers determine the quality of the produced debugging information. Fixes #22168. Change-Id: I1b994ef2262aa9b88b68eb6e883695d1103acc58 Reviewed-on: https://go-review.googlesource.com/71430 Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 193088b commit 2c1d2e0

File tree

4 files changed

+81
-1
lines changed

4 files changed

+81
-1
lines changed

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

+58
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"bytes"
1212
"cmd/compile/internal/ssa"
1313
"cmd/compile/internal/types"
14+
"cmd/internal/dwarf"
1415
"cmd/internal/obj"
1516
"cmd/internal/objabi"
1617
"cmd/internal/src"
@@ -239,6 +240,11 @@ func Main(archInit func(*Arch)) {
239240
flag.StringVar(&benchfile, "bench", "", "append benchmark times to `file`")
240241
objabi.Flagparse(usage)
241242

243+
// Record flags that affect the build result. (And don't
244+
// record flags that don't, since that would cause spurious
245+
// changes in the binary.)
246+
recordFlags("B", "N", "l", "msan", "race", "shared", "dynlink", "dwarflocationlists")
247+
242248
Ctxt.Flag_shared = flag_dynlink || flag_shared
243249
Ctxt.Flag_dynlink = flag_dynlink
244250
Ctxt.Flag_optimize = Debug['N'] == 0
@@ -1195,3 +1201,55 @@ func concurrentBackendAllowed() bool {
11951201
}
11961202
return true
11971203
}
1204+
1205+
// recordFlags records the specified command-line flags to be placed
1206+
// in the DWARF info.
1207+
func recordFlags(flags ...string) {
1208+
if myimportpath == "" {
1209+
// We can't record the flags if we don't know what the
1210+
// package name is.
1211+
return
1212+
}
1213+
1214+
type BoolFlag interface {
1215+
IsBoolFlag() bool
1216+
}
1217+
type CountFlag interface {
1218+
IsCountFlag() bool
1219+
}
1220+
var cmd bytes.Buffer
1221+
for _, name := range flags {
1222+
f := flag.Lookup(name)
1223+
if f == nil {
1224+
continue
1225+
}
1226+
getter := f.Value.(flag.Getter)
1227+
if getter.String() == f.DefValue {
1228+
// Flag has default value, so omit it.
1229+
continue
1230+
}
1231+
if bf, ok := f.Value.(BoolFlag); ok && bf.IsBoolFlag() {
1232+
val, ok := getter.Get().(bool)
1233+
if ok && val {
1234+
fmt.Fprintf(&cmd, " -%s", f.Name)
1235+
continue
1236+
}
1237+
}
1238+
if cf, ok := f.Value.(CountFlag); ok && cf.IsCountFlag() {
1239+
val, ok := getter.Get().(int)
1240+
if ok && val == 1 {
1241+
fmt.Fprintf(&cmd, " -%s", f.Name)
1242+
continue
1243+
}
1244+
}
1245+
fmt.Fprintf(&cmd, " -%s=%v", f.Name, getter.Get())
1246+
}
1247+
1248+
if cmd.Len() == 0 {
1249+
return
1250+
}
1251+
s := Ctxt.Lookup(dwarf.CUInfoPrefix + "producer." + myimportpath)
1252+
s.Type = objabi.SDWARFINFO
1253+
Ctxt.Data = append(Ctxt.Data, s)
1254+
s.P = cmd.Bytes()[1:]
1255+
}

src/cmd/internal/dwarf/dwarf.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,14 @@ 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
24+
// ConstInfoPrefix is the prefix for all symbols containing DWARF info
2525
// entries that contain constants.
2626
const ConstInfoPrefix = "go.constinfo."
2727

28+
// CUInfoPrefix is the prefix for symbols containing information to
29+
// populate the DWARF compilation unit info entries.
30+
const CUInfoPrefix = "go.cuinfo."
31+
2832
// Sym represents a symbol.
2933
type Sym interface {
3034
Len() int64

src/cmd/internal/objabi/flag.go

+8
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,18 @@ func (c *count) Set(s string) error {
9494
return nil
9595
}
9696

97+
func (c *count) Get() interface{} {
98+
return int(*c)
99+
}
100+
97101
func (c *count) IsBoolFlag() bool {
98102
return true
99103
}
100104

105+
func (c *count) IsCountFlag() bool {
106+
return true
107+
}
108+
101109
type fn0 func()
102110

103111
func (f fn0) Set(s string) error {

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

+10
Original file line numberDiff line numberDiff line change
@@ -1059,7 +1059,17 @@ func writelines(ctxt *Link, lib *sym.Library, textp []*sym.Symbol, ls *sym.Symbo
10591059
// the linker directory. If we move CU construction into the
10601060
// compiler, this should happen naturally.
10611061
newattr(dwinfo, dwarf.DW_AT_comp_dir, dwarf.DW_CLS_STRING, int64(len(compDir)), compDir)
1062+
producerExtra := ctxt.Syms.Lookup(dwarf.CUInfoPrefix+"producer."+lib.Pkg, 0)
10621063
producer := "Go cmd/compile " + objabi.Version
1064+
if len(producerExtra.P) > 0 {
1065+
// We put a semicolon before the flags to clearly
1066+
// separate them from the version, which can be long
1067+
// and have lots of weird things in it in development
1068+
// versions. We promise not to put a semicolon in the
1069+
// version, so it should be safe for readers to scan
1070+
// forward to the semicolon.
1071+
producer += "; " + string(producerExtra.P)
1072+
}
10631073
newattr(dwinfo, dwarf.DW_AT_producer, dwarf.DW_CLS_STRING, int64(len(producer)), producer)
10641074

10651075
// Write .debug_line Line Number Program Header (sec 6.2.4)

0 commit comments

Comments
 (0)