Skip to content

Commit 807761f

Browse files
committed
cmd/link: revert/revise CL 98075 because LLDB is very picky now
This was originally Revert "cmd/link: fix up debug_range for dsymutil (revert CL 72371)" which has the effect of no longer using Base Address Selection Entries in DWARF. However, the build-time costs of that are about 2%, so instead the hacky fixup that generated technically incorrect DWARF was removed from the linker, and the choice is instead made in the compiler, dependent on platform, but also under control of a flag so that we can report this bug against LLDB/dsymutil/dwarfdump (really, the LLVM dwarf libraries). This however does not solve #31188; debugging still fails, but dwarfdump no longer complains. There are at least two LLDB bugs involved, and this change will at allow us to report them without them being rejected because our now-obsolete workaround for the first bug creates not-quite-DWARF. Updates #31188. Change-Id: I5300c51ad202147bab7333329ebe961623d2b47d Reviewed-on: https://go-review.googlesource.com/c/go/+/170638 Run-TryBot: David Chase <[email protected]> Reviewed-by: Heschi Kreinick <[email protected]>
1 parent 68819fb commit 807761f

File tree

8 files changed

+131
-126
lines changed

8 files changed

+131
-126
lines changed

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,12 @@ func Main(archInit func(*Arch)) {
140140
Ctxt.DiagFlush = flusherrors
141141
Ctxt.Bso = bufio.NewWriter(os.Stdout)
142142

143+
// UseBASEntries is preferred because it shaves about 2% off build time, but LLDB, dsymutil, and dwarfdump
144+
// on Darwin don't support it properly, especially since macOS 10.14 (Mojave). This is exposed as a flag
145+
// to allow testing with LLVM tools on Linux, and to help with reporting this bug to the LLVM project.
146+
// See bugs 31188 and 21945 (CLs 170638, 98075, 72371).
147+
Ctxt.UseBASEntries = Ctxt.Headtype != objabi.Hdarwin
148+
143149
localpkg = types.NewPkg("", "")
144150
localpkg.Prefix = "\"\""
145151

@@ -254,12 +260,13 @@ func Main(archInit func(*Arch)) {
254260
flag.StringVar(&mutexprofile, "mutexprofile", "", "write mutex profile to `file`")
255261
flag.StringVar(&benchfile, "bench", "", "append benchmark times to `file`")
256262
flag.BoolVar(&newescape, "newescape", true, "enable new escape analysis")
263+
flag.BoolVar(&Ctxt.UseBASEntries, "dwarfbasentries", Ctxt.UseBASEntries, "use base address selection entries in DWARF")
257264
objabi.Flagparse(usage)
258265

259266
// Record flags that affect the build result. (And don't
260267
// record flags that don't, since that would cause spurious
261268
// changes in the binary.)
262-
recordFlags("B", "N", "l", "msan", "race", "shared", "dynlink", "dwarflocationlists", "newescape")
269+
recordFlags("B", "N", "l", "msan", "race", "shared", "dynlink", "dwarflocationlists", "newescape", "dwarfbasentries")
263270

264271
Ctxt.Flag_shared = flag_dynlink || flag_shared
265272
Ctxt.Flag_dynlink = flag_dynlink

src/cmd/compile/internal/ssa/debug.go

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,6 +1077,12 @@ func (state *debugState) writePendingEntry(varID VarID, endBlock, endValue ID) {
10771077
// PutLocationList adds list (a location list in its intermediate representation) to listSym.
10781078
func (debugInfo *FuncDebug) PutLocationList(list []byte, ctxt *obj.Link, listSym, startPC *obj.LSym) {
10791079
getPC := debugInfo.GetPC
1080+
1081+
if ctxt.UseBASEntries {
1082+
listSym.WriteInt(ctxt, listSym.Size, ctxt.Arch.PtrSize, ^0)
1083+
listSym.WriteAddr(ctxt, listSym.Size, ctxt.Arch.PtrSize, startPC, 0)
1084+
}
1085+
10801086
// Re-read list, translating its address from block/value ID to PC.
10811087
for i := 0; i < len(list); {
10821088
begin := getPC(decodeValue(ctxt, readPtr(ctxt, list[i:])))
@@ -1090,17 +1096,21 @@ func (debugInfo *FuncDebug) PutLocationList(list []byte, ctxt *obj.Link, listSym
10901096
end = 1
10911097
}
10921098

1093-
writePtr(ctxt, list[i:], uint64(begin))
1094-
writePtr(ctxt, list[i+ctxt.Arch.PtrSize:], uint64(end))
1099+
if ctxt.UseBASEntries {
1100+
listSym.WriteInt(ctxt, listSym.Size, ctxt.Arch.PtrSize, int64(begin))
1101+
listSym.WriteInt(ctxt, listSym.Size, ctxt.Arch.PtrSize, int64(end))
1102+
} else {
1103+
listSym.WriteCURelativeAddr(ctxt, listSym.Size, startPC, int64(begin))
1104+
listSym.WriteCURelativeAddr(ctxt, listSym.Size, startPC, int64(end))
1105+
}
1106+
10951107
i += 2 * ctxt.Arch.PtrSize
1096-
i += 2 + int(ctxt.Arch.ByteOrder.Uint16(list[i:]))
1108+
datalen := 2 + int(ctxt.Arch.ByteOrder.Uint16(list[i:]))
1109+
listSym.WriteBytes(ctxt, listSym.Size, list[i:i+datalen]) // copy datalen and location encoding
1110+
i += datalen
10971111
}
10981112

1099-
// Base address entry.
1100-
listSym.WriteInt(ctxt, listSym.Size, ctxt.Arch.PtrSize, ^0)
1101-
listSym.WriteAddr(ctxt, listSym.Size, ctxt.Arch.PtrSize, startPC, 0)
11021113
// Location list contents, now with real PCs.
1103-
listSym.WriteBytes(ctxt, listSym.Size, list)
11041114
// End entry.
11051115
listSym.WriteInt(ctxt, listSym.Size, ctxt.Arch.PtrSize, 0)
11061116
listSym.WriteInt(ctxt, listSym.Size, ctxt.Arch.PtrSize, 0)

src/cmd/internal/dwarf/dwarf.go

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -91,18 +91,19 @@ type Range struct {
9191
// This container is used by the PutFunc* variants below when
9292
// creating the DWARF subprogram DIE(s) for a function.
9393
type FnState struct {
94-
Name string
95-
Importpath string
96-
Info Sym
97-
Filesym Sym
98-
Loc Sym
99-
Ranges Sym
100-
Absfn Sym
101-
StartPC Sym
102-
Size int64
103-
External bool
104-
Scopes []Scope
105-
InlCalls InlCalls
94+
Name string
95+
Importpath string
96+
Info Sym
97+
Filesym Sym
98+
Loc Sym
99+
Ranges Sym
100+
Absfn Sym
101+
StartPC Sym
102+
Size int64
103+
External bool
104+
Scopes []Scope
105+
InlCalls InlCalls
106+
UseBASEntries bool
106107
}
107108

108109
func EnableLogging(doit bool) {
@@ -181,6 +182,7 @@ type Context interface {
181182
AddInt(s Sym, size int, i int64)
182183
AddBytes(s Sym, b []byte)
183184
AddAddress(s Sym, t interface{}, ofs int64)
185+
AddCURelativeAddress(s Sym, t interface{}, ofs int64)
184186
AddSectionOffset(s Sym, size int, t interface{}, ofs int64)
185187
AddDWARFAddrSectionOffset(s Sym, t interface{}, ofs int64)
186188
CurrentOffset(s Sym) int64
@@ -987,18 +989,11 @@ func PutIntConst(ctxt Context, info, typ Sym, name string, val int64) {
987989
putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_sdata, DW_CLS_CONSTANT, val, nil)
988990
}
989991

990-
// PutRanges writes a range table to sym. All addresses in ranges are
991-
// relative to some base address. If base is not nil, then they're
992-
// relative to the start of base. If base is nil, then the caller must
993-
// arrange a base address some other way (such as a DW_AT_low_pc
994-
// attribute).
995-
func PutRanges(ctxt Context, sym Sym, base Sym, ranges []Range) {
992+
// PutBasedRanges writes a range table to sym. All addresses in ranges are
993+
// relative to some base address, which must be arranged by the caller
994+
// (e.g., with a DW_AT_low_pc attribute, or in a BASE-prefixed range).
995+
func PutBasedRanges(ctxt Context, sym Sym, ranges []Range) {
996996
ps := ctxt.PtrSize()
997-
// Write base address entry.
998-
if base != nil {
999-
ctxt.AddInt(sym, ps, -1)
1000-
ctxt.AddAddress(sym, base, 0)
1001-
}
1002997
// Write ranges.
1003998
for _, r := range ranges {
1004999
ctxt.AddInt(sym, ps, r.Start)
@@ -1009,6 +1004,31 @@ func PutRanges(ctxt Context, sym Sym, base Sym, ranges []Range) {
10091004
ctxt.AddInt(sym, ps, 0)
10101005
}
10111006

1007+
// PutRanges writes a range table to s.Ranges.
1008+
// All addresses in ranges are relative to s.base.
1009+
func (s *FnState) PutRanges(ctxt Context, ranges []Range) {
1010+
ps := ctxt.PtrSize()
1011+
sym, base := s.Ranges, s.StartPC
1012+
1013+
if s.UseBASEntries {
1014+
// Using a Base Address Selection Entry reduces the number of relocations, but
1015+
// this is not done on macOS because it is not supported by dsymutil/dwarfdump/lldb
1016+
ctxt.AddInt(sym, ps, -1)
1017+
ctxt.AddAddress(sym, base, 0)
1018+
PutBasedRanges(ctxt, sym, ranges)
1019+
return
1020+
}
1021+
1022+
// Write ranges full of relocations
1023+
for _, r := range ranges {
1024+
ctxt.AddCURelativeAddress(sym, base, r.Start)
1025+
ctxt.AddCURelativeAddress(sym, base, r.End)
1026+
}
1027+
// Write trailer.
1028+
ctxt.AddInt(sym, ps, 0)
1029+
ctxt.AddInt(sym, ps, 0)
1030+
}
1031+
10121032
// Return TRUE if the inlined call in the specified slot is empty,
10131033
// meaning it has a zero-length range (no instructions), and all
10141034
// of its children are empty.
@@ -1202,7 +1222,7 @@ func PutInlinedFunc(ctxt Context, s *FnState, callersym Sym, callIdx int) error
12021222

12031223
if abbrev == DW_ABRV_INLINED_SUBROUTINE_RANGES {
12041224
putattr(ctxt, s.Info, abbrev, DW_FORM_sec_offset, DW_CLS_PTR, s.Ranges.Len(), s.Ranges)
1205-
PutRanges(ctxt, s.Ranges, s.StartPC, ic.Ranges)
1225+
s.PutRanges(ctxt, ic.Ranges)
12061226
} else {
12071227
st := ic.Ranges[0].Start
12081228
en := ic.Ranges[0].End
@@ -1357,7 +1377,7 @@ func putscope(ctxt Context, s *FnState, scopes []Scope, curscope int32, fnabbrev
13571377
Uleb128put(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_RANGES)
13581378
putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_RANGES, DW_FORM_sec_offset, DW_CLS_PTR, s.Ranges.Len(), s.Ranges)
13591379

1360-
PutRanges(ctxt, s.Ranges, s.StartPC, scope.Ranges)
1380+
s.PutRanges(ctxt, scope.Ranges)
13611381
}
13621382

13631383
curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf)

src/cmd/internal/obj/data.go

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,7 @@ func (s *LSym) WriteInt(ctxt *Link, off int64, siz int, i int64) {
112112
}
113113
}
114114

115-
// WriteAddr writes an address of size siz into s at offset off.
116-
// rsym and roff specify the relocation for the address.
117-
func (s *LSym) WriteAddr(ctxt *Link, off int64, siz int, rsym *LSym, roff int64) {
115+
func (s *LSym) writeAddr(ctxt *Link, off int64, siz int, rsym *LSym, roff int64, rtype objabi.RelocType) {
118116
// Allow 4-byte addresses for DWARF.
119117
if siz != ctxt.Arch.PtrSize && siz != 4 {
120118
ctxt.Diag("WriteAddr: bad address size %d in %s", siz, s.Name)
@@ -127,10 +125,24 @@ func (s *LSym) WriteAddr(ctxt *Link, off int64, siz int, rsym *LSym, roff int64)
127125
}
128126
r.Siz = uint8(siz)
129127
r.Sym = rsym
130-
r.Type = objabi.R_ADDR
128+
r.Type = rtype
131129
r.Add = roff
132130
}
133131

132+
// WriteAddr writes an address of size siz into s at offset off.
133+
// rsym and roff specify the relocation for the address.
134+
func (s *LSym) WriteAddr(ctxt *Link, off int64, siz int, rsym *LSym, roff int64) {
135+
s.writeAddr(ctxt, off, siz, rsym, roff, objabi.R_ADDR)
136+
}
137+
138+
// WriteCURelativeAddr writes a pointer-sized address into s at offset off.
139+
// rsym and roff specify the relocation for the address which will be
140+
// resolved by the linker to an offset from the DW_AT_low_pc attribute of
141+
// the DWARF Compile Unit of rsym.
142+
func (s *LSym) WriteCURelativeAddr(ctxt *Link, off int64, rsym *LSym, roff int64) {
143+
s.writeAddr(ctxt, off, ctxt.Arch.PtrSize, rsym, roff, objabi.R_ADDRCUOFF)
144+
}
145+
134146
// WriteOff writes a 4 byte offset to rsym+roff into s at offset off.
135147
// After linking the 4 bytes stored at s+off will be
136148
// rsym+roff-(start of section that s is in).

src/cmd/internal/obj/link.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,7 @@ type Link struct {
648648

649649
InParallel bool // parallel backend phase in effect
650650
Framepointer_enabled bool
651+
UseBASEntries bool // Use Base Address Selection Entries in location lists and PC ranges
651652

652653
// state for writing objects
653654
Text []*LSym

src/cmd/internal/obj/objfile.go

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,11 @@ func (c dwCtxt) AddAddress(s dwarf.Sym, data interface{}, value int64) {
471471
ls.WriteInt(c.Link, ls.Size, size, value)
472472
}
473473
}
474+
func (c dwCtxt) AddCURelativeAddress(s dwarf.Sym, data interface{}, value int64) {
475+
ls := s.(*LSym)
476+
rsym := data.(*LSym)
477+
ls.WriteCURelativeAddr(c.Link, ls.Size, rsym, value)
478+
}
474479
func (c dwCtxt) AddSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64) {
475480
panic("should be used only in the linker")
476481
}
@@ -578,18 +583,19 @@ func (ctxt *Link) populateDWARF(curfn interface{}, s *LSym, myimportpath string)
578583
dwctxt := dwCtxt{ctxt}
579584
filesym := ctxt.fileSymbol(s)
580585
fnstate := &dwarf.FnState{
581-
Name: s.Name,
582-
Importpath: myimportpath,
583-
Info: info,
584-
Filesym: filesym,
585-
Loc: loc,
586-
Ranges: ranges,
587-
Absfn: absfunc,
588-
StartPC: s,
589-
Size: s.Size,
590-
External: !s.Static(),
591-
Scopes: scopes,
592-
InlCalls: inlcalls,
586+
Name: s.Name,
587+
Importpath: myimportpath,
588+
Info: info,
589+
Filesym: filesym,
590+
Loc: loc,
591+
Ranges: ranges,
592+
Absfn: absfunc,
593+
StartPC: s,
594+
Size: s.Size,
595+
External: !s.Static(),
596+
Scopes: scopes,
597+
InlCalls: inlcalls,
598+
UseBASEntries: ctxt.UseBASEntries,
593599
}
594600
if absfunc != nil {
595601
err = dwarf.PutAbstractFunc(dwctxt, fnstate)
@@ -630,13 +636,14 @@ func (ctxt *Link) DwarfAbstractFunc(curfn interface{}, s *LSym, myimportpath str
630636
dwctxt := dwCtxt{ctxt}
631637
filesym := ctxt.fileSymbol(s)
632638
fnstate := dwarf.FnState{
633-
Name: s.Name,
634-
Importpath: myimportpath,
635-
Info: absfn,
636-
Filesym: filesym,
637-
Absfn: absfn,
638-
External: !s.Static(),
639-
Scopes: scopes,
639+
Name: s.Name,
640+
Importpath: myimportpath,
641+
Info: absfn,
642+
Filesym: filesym,
643+
Absfn: absfn,
644+
External: !s.Static(),
645+
Scopes: scopes,
646+
UseBASEntries: ctxt.UseBASEntries,
640647
}
641648
if err := dwarf.PutAbstractFunc(dwctxt, &fnstate); err != nil {
642649
ctxt.Diag("emitting DWARF for %s failed: %v", s.Name, err)

0 commit comments

Comments
 (0)