Commit 018642d6 authored by Alessandro Arzilli's avatar Alessandro Arzilli Committed by Austin Clements

compile, link: remove base address selector from DWARF range lists

Dsymutil, an utility used on macOS when externally linking executables,
does not support base address selector entries in debug_ranges.

To work around this deficiency this commit removes base address
selectors from debug_ranges and emits instead a list composed only of
compile unit relative addresses.

A new type of relocation is introduced, R_ADDRCUOFF, similar to
R_ADDROFF, that relocates an address to its offset from the low_pc of
the symbol's compile unit.

Fixes #21945

Change-Id: Ie991f9bc1afda2b49ac5d734eb41c37d3a37e554
Reviewed-on: https://go-review.googlesource.com/72371
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarAustin Clements <austin@google.com>
Reviewed-by: 's avatarHeschi Kreinick <heschi@google.com>
parent 56178649
...@@ -121,6 +121,7 @@ type Context interface { ...@@ -121,6 +121,7 @@ type Context interface {
AddInt(s Sym, size int, i int64) AddInt(s Sym, size int, i int64)
AddBytes(s Sym, b []byte) AddBytes(s Sym, b []byte)
AddAddress(s Sym, t interface{}, ofs int64) AddAddress(s Sym, t interface{}, ofs int64)
AddCURelativeAddress(s Sym, t interface{}, ofs int64)
AddSectionOffset(s Sym, size int, t interface{}, ofs int64) AddSectionOffset(s Sym, size int, t interface{}, ofs int64)
AddString(s Sym, v string) AddString(s Sym, v string)
AddFileRef(s Sym, f interface{}) AddFileRef(s Sym, f interface{})
...@@ -773,15 +774,18 @@ func PutIntConst(ctxt Context, info, typ Sym, name string, val int64) { ...@@ -773,15 +774,18 @@ func PutIntConst(ctxt Context, info, typ Sym, name string, val int64) {
// attribute). // attribute).
func PutRanges(ctxt Context, sym Sym, base Sym, ranges []Range) { func PutRanges(ctxt Context, sym Sym, base Sym, ranges []Range) {
ps := ctxt.PtrSize() ps := ctxt.PtrSize()
// Write base address entry.
if base != nil {
ctxt.AddInt(sym, ps, -1)
ctxt.AddAddress(sym, base, 0)
}
// Write ranges. // Write ranges.
// We do not emit base address entries here, even though they would reduce
// the number of relocations, because dsymutil (which is used on macOS when
// linking externally) does not support them.
for _, r := range ranges { for _, r := range ranges {
ctxt.AddInt(sym, ps, r.Start) if base == nil {
ctxt.AddInt(sym, ps, r.End) ctxt.AddInt(sym, ps, r.Start)
ctxt.AddInt(sym, ps, r.End)
} else {
ctxt.AddCURelativeAddress(sym, base, r.Start)
ctxt.AddCURelativeAddress(sym, base, r.End)
}
} }
// Write trailer. // Write trailer.
ctxt.AddInt(sym, ps, 0) ctxt.AddInt(sym, ps, 0)
......
...@@ -117,9 +117,7 @@ func (s *LSym) WriteInt(ctxt *Link, off int64, siz int, i int64) { ...@@ -117,9 +117,7 @@ func (s *LSym) WriteInt(ctxt *Link, off int64, siz int, i int64) {
} }
} }
// WriteAddr writes an address of size siz into s at offset off. func (s *LSym) writeAddr(ctxt *Link, off int64, siz int, rsym *LSym, roff int64, rtype objabi.RelocType) {
// rsym and roff specify the relocation for the address.
func (s *LSym) WriteAddr(ctxt *Link, off int64, siz int, rsym *LSym, roff int64) {
// Allow 4-byte addresses for DWARF. // Allow 4-byte addresses for DWARF.
if siz != ctxt.Arch.PtrSize && siz != 4 { if siz != ctxt.Arch.PtrSize && siz != 4 {
ctxt.Diag("WriteAddr: bad address size %d in %s", siz, s.Name) ctxt.Diag("WriteAddr: bad address size %d in %s", siz, s.Name)
...@@ -132,10 +130,24 @@ func (s *LSym) WriteAddr(ctxt *Link, off int64, siz int, rsym *LSym, roff int64) ...@@ -132,10 +130,24 @@ func (s *LSym) WriteAddr(ctxt *Link, off int64, siz int, rsym *LSym, roff int64)
} }
r.Siz = uint8(siz) r.Siz = uint8(siz)
r.Sym = rsym r.Sym = rsym
r.Type = objabi.R_ADDR r.Type = rtype
r.Add = roff r.Add = roff
} }
// WriteAddr writes an address of size siz into s at offset off.
// rsym and roff specify the relocation for the address.
func (s *LSym) WriteAddr(ctxt *Link, off int64, siz int, rsym *LSym, roff int64) {
s.writeAddr(ctxt, off, siz, rsym, roff, objabi.R_ADDR)
}
// WriteCURelativeAddr writes a pointer-sized address into s at offset off.
// rsym and roff specify the relocation for the address which will be
// resolved by the linker to an offset from the DW_AT_low_pc attribute of
// the DWARF Compile Unit of rsym.
func (s *LSym) WriteCURelativeAddr(ctxt *Link, off int64, rsym *LSym, roff int64) {
s.writeAddr(ctxt, off, ctxt.Arch.PtrSize, rsym, roff, objabi.R_ADDRCUOFF)
}
// WriteOff writes a 4 byte offset to rsym+roff into s at offset off. // WriteOff writes a 4 byte offset to rsym+roff into s at offset off.
// After linking the 4 bytes stored at s+off will be // After linking the 4 bytes stored at s+off will be
// rsym+roff-(start of section that s is in). // rsym+roff-(start of section that s is in).
......
...@@ -453,6 +453,11 @@ func (c dwCtxt) AddAddress(s dwarf.Sym, data interface{}, value int64) { ...@@ -453,6 +453,11 @@ func (c dwCtxt) AddAddress(s dwarf.Sym, data interface{}, value int64) {
ls.WriteInt(c.Link, ls.Size, size, value) ls.WriteInt(c.Link, ls.Size, size, value)
} }
} }
func (c dwCtxt) AddCURelativeAddress(s dwarf.Sym, data interface{}, value int64) {
ls := s.(*LSym)
rsym := data.(*LSym)
ls.WriteCURelativeAddr(c.Link, ls.Size, rsym, value)
}
func (c dwCtxt) AddSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64) { func (c dwCtxt) AddSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64) {
ls := s.(*LSym) ls := s.(*LSym)
rsym := t.(*LSym) rsym := t.(*LSym)
......
...@@ -190,6 +190,9 @@ const ( ...@@ -190,6 +190,9 @@ const (
// R_ADDRMIPSTLS (only used on mips64) resolves to the low 16 bits of a TLS // R_ADDRMIPSTLS (only used on mips64) resolves to the low 16 bits of a TLS
// address (offset from thread pointer), by encoding it into the instruction. // address (offset from thread pointer), by encoding it into the instruction.
R_ADDRMIPSTLS R_ADDRMIPSTLS
// R_ADDRCUOFF resolves to a pointer-sized offset from the start of the
// symbol's DWARF compile unit.
R_ADDRCUOFF
) )
// IsDirectJump returns whether r is a relocation for a direct jump. // IsDirectJump returns whether r is a relocation for a direct jump.
......
...@@ -4,9 +4,9 @@ package objabi ...@@ -4,9 +4,9 @@ package objabi
import "fmt" import "fmt"
const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_WEAKADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_METHODOFFR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_PCRELDBLR_ADDRMIPSUR_ADDRMIPSTLS" const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_WEAKADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_METHODOFFR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_PCRELDBLR_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFF"
var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 60, 66, 72, 81, 92, 101, 112, 122, 129, 136, 144, 152, 160, 166, 172, 178, 188, 197, 208, 219, 229, 238, 251, 265, 279, 293, 309, 323, 337, 348, 362, 377, 394, 412, 433, 443, 454, 467} var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 60, 66, 72, 81, 92, 101, 112, 122, 129, 136, 144, 152, 160, 166, 172, 178, 188, 197, 208, 219, 229, 238, 251, 265, 279, 293, 309, 323, 337, 348, 362, 377, 394, 412, 433, 443, 454, 467, 478}
func (i RelocType) String() string { func (i RelocType) String() string {
i -= 1 i -= 1
......
...@@ -367,6 +367,11 @@ func relocsym(ctxt *Link, s *sym.Symbol) { ...@@ -367,6 +367,11 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
o = Symaddr(r.Sym) - int64(r.Sym.Sect.Vaddr) + r.Add o = Symaddr(r.Sym) - int64(r.Sym.Sect.Vaddr) + r.Add
} }
case objabi.R_ADDRCUOFF:
// debug_range and debug_loc elements use this relocation type to get an
// offset from the start of the compile unit.
o = Symaddr(r.Sym) + r.Add - Symaddr(r.Sym.Lib.Textp[0])
// r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call. // r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call.
case objabi.R_GOTPCREL: case objabi.R_GOTPCREL:
if ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin && r.Sym != nil && r.Sym.Type != sym.SCONST { if ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin && r.Sym != nil && r.Sym.Type != sym.SCONST {
......
...@@ -118,10 +118,17 @@ func deadcode(ctxt *Link) { ...@@ -118,10 +118,17 @@ func deadcode(ctxt *Link) {
} }
} }
for _, lib := range ctxt.Library {
lib.Textp = lib.Textp[:0]
}
// Remove dead text but keep file information (z symbols). // Remove dead text but keep file information (z symbols).
textp := make([]*sym.Symbol, 0, len(ctxt.Textp)) textp := make([]*sym.Symbol, 0, len(ctxt.Textp))
for _, s := range ctxt.Textp { for _, s := range ctxt.Textp {
if s.Attr.Reachable() { if s.Attr.Reachable() {
if s.Lib != nil {
s.Lib.Textp = append(s.Lib.Textp, s)
}
textp = append(textp, s) textp = append(textp, s)
} }
} }
......
...@@ -49,6 +49,13 @@ func (c dwctxt) AddAddress(s dwarf.Sym, data interface{}, value int64) { ...@@ -49,6 +49,13 @@ func (c dwctxt) AddAddress(s dwarf.Sym, data interface{}, value int64) {
s.(*sym.Symbol).AddAddrPlus(c.linkctxt.Arch, data.(*sym.Symbol), value) s.(*sym.Symbol).AddAddrPlus(c.linkctxt.Arch, data.(*sym.Symbol), value)
} }
func (c dwctxt) AddCURelativeAddress(s dwarf.Sym, data interface{}, value int64) {
if value != 0 {
value -= (data.(*sym.Symbol)).Value
}
s.(*sym.Symbol).AddCURelativeAddrPlus(c.linkctxt.Arch, data.(*sym.Symbol), value)
}
func (c dwctxt) AddSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64) { func (c dwctxt) AddSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64) {
ls := s.(*sym.Symbol) ls := s.(*sym.Symbol)
switch size { switch size {
...@@ -843,7 +850,6 @@ func defdwsymb(ctxt *Link, s *sym.Symbol, str string, t SymbolType, v int64, got ...@@ -843,7 +850,6 @@ func defdwsymb(ctxt *Link, s *sym.Symbol, str string, t SymbolType, v int64, got
// debug-related data. // debug-related data.
type compilationUnit struct { type compilationUnit struct {
lib *sym.Library lib *sym.Library
textp []*sym.Symbol // Function symbols in this package
consts *sym.Symbol // Package constants DIEs consts *sym.Symbol // Package constants DIEs
pcs []dwarf.Range // PC ranges, relative to textp[0] pcs []dwarf.Range // PC ranges, relative to textp[0]
dwinfo *dwarf.DWDie // CU root DIE dwinfo *dwarf.DWDie // CU root DIE
...@@ -869,7 +875,6 @@ func getCompilationUnits(ctxt *Link) []*compilationUnit { ...@@ -869,7 +875,6 @@ func getCompilationUnits(ctxt *Link) []*compilationUnit {
units = append(units, unit) units = append(units, unit)
index[s.Lib] = unit index[s.Lib] = unit
} }
unit.textp = append(unit.textp, s)
// Update PC ranges. // Update PC ranges.
// //
...@@ -879,10 +884,10 @@ func getCompilationUnits(ctxt *Link) []*compilationUnit { ...@@ -879,10 +884,10 @@ func getCompilationUnits(ctxt *Link) []*compilationUnit {
// only create boundaries between symbols from // only create boundaries between symbols from
// different units. // different units.
if prevUnit != unit { if prevUnit != unit {
unit.pcs = append(unit.pcs, dwarf.Range{Start: s.Value - unit.textp[0].Value}) unit.pcs = append(unit.pcs, dwarf.Range{Start: s.Value - unit.lib.Textp[0].Value})
prevUnit = unit prevUnit = unit
} }
unit.pcs[len(unit.pcs)-1].End = s.Value - unit.textp[0].Value + s.Size unit.pcs[len(unit.pcs)-1].End = s.Value - unit.lib.Textp[0].Value + s.Size
} }
return units return units
} }
...@@ -1612,8 +1617,8 @@ func dwarfgeneratedebugsyms(ctxt *Link) { ...@@ -1612,8 +1617,8 @@ func dwarfgeneratedebugsyms(ctxt *Link) {
debugRanges.Attr |= sym.AttrReachable debugRanges.Attr |= sym.AttrReachable
syms = append(syms, debugLine) syms = append(syms, debugLine)
for _, u := range units { for _, u := range units {
u.dwinfo, u.funcDIEs = writelines(ctxt, u.lib, u.textp, debugLine) u.dwinfo, u.funcDIEs = writelines(ctxt, u.lib, u.lib.Textp, debugLine)
writepcranges(ctxt, u.dwinfo, u.textp[0], u.pcs, debugRanges) writepcranges(ctxt, u.dwinfo, u.lib.Textp[0], u.pcs, debugRanges)
} }
synthesizestringtypes(ctxt, dwtypes.Child) synthesizestringtypes(ctxt, dwtypes.Child)
......
...@@ -133,7 +133,7 @@ func (s *Symbol) SetUint(arch *sys.Arch, r int64, v uint64) int64 { ...@@ -133,7 +133,7 @@ func (s *Symbol) SetUint(arch *sys.Arch, r int64, v uint64) int64 {
return s.setUintXX(arch, r, v, int64(arch.PtrSize)) return s.setUintXX(arch, r, v, int64(arch.PtrSize))
} }
func (s *Symbol) AddAddrPlus(arch *sys.Arch, t *Symbol, add int64) int64 { func (s *Symbol) addAddrPlus(arch *sys.Arch, t *Symbol, add int64, typ objabi.RelocType) int64 {
if s.Type == 0 { if s.Type == 0 {
s.Type = SDATA s.Type = SDATA
} }
...@@ -145,11 +145,19 @@ func (s *Symbol) AddAddrPlus(arch *sys.Arch, t *Symbol, add int64) int64 { ...@@ -145,11 +145,19 @@ func (s *Symbol) AddAddrPlus(arch *sys.Arch, t *Symbol, add int64) int64 {
r.Sym = t r.Sym = t
r.Off = int32(i) r.Off = int32(i)
r.Siz = uint8(arch.PtrSize) r.Siz = uint8(arch.PtrSize)
r.Type = objabi.R_ADDR r.Type = typ
r.Add = add r.Add = add
return i + int64(r.Siz) return i + int64(r.Siz)
} }
func (s *Symbol) AddAddrPlus(arch *sys.Arch, t *Symbol, add int64) int64 {
return s.addAddrPlus(arch, t, add, objabi.R_ADDR)
}
func (s *Symbol) AddCURelativeAddrPlus(arch *sys.Arch, t *Symbol, add int64) int64 {
return s.addAddrPlus(arch, t, add, objabi.R_ADDRCUOFF)
}
func (s *Symbol) AddPCRelPlus(arch *sys.Arch, t *Symbol, add int64) int64 { func (s *Symbol) AddPCRelPlus(arch *sys.Arch, t *Symbol, add int64) int64 {
if s.Type == 0 { if s.Type == 0 {
s.Type = SDATA s.Type = SDATA
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment