]> Cypherpunks repositories - gostls13.git/commitdiff
compile, link: remove base address selector from DWARF range lists
authorAlessandro Arzilli <alessandro.arzilli@gmail.com>
Sat, 21 Oct 2017 10:45:23 +0000 (12:45 +0200)
committerAustin Clements <austin@google.com>
Wed, 1 Nov 2017 14:35:30 +0000 (14:35 +0000)
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: Austin Clements <austin@google.com>
Reviewed-by: Heschi Kreinick <heschi@google.com>
src/cmd/internal/dwarf/dwarf.go
src/cmd/internal/obj/data.go
src/cmd/internal/obj/objfile.go
src/cmd/internal/objabi/reloctype.go
src/cmd/internal/objabi/reloctype_string.go
src/cmd/link/internal/ld/data.go
src/cmd/link/internal/ld/deadcode.go
src/cmd/link/internal/ld/dwarf.go
src/cmd/link/internal/sym/symbol.go

index 8f7049df09f5334a85ed1133183ca1674841f727..ce1f9795e699b1f564aa1a2bcf83629b0e3d8220 100644 (file)
@@ -121,6 +121,7 @@ type Context interface {
        AddInt(s Sym, size int, i int64)
        AddBytes(s Sym, b []byte)
        AddAddress(s Sym, t interface{}, ofs int64)
+       AddCURelativeAddress(s Sym, t interface{}, ofs int64)
        AddSectionOffset(s Sym, size int, t interface{}, ofs int64)
        AddString(s Sym, v string)
        AddFileRef(s Sym, f interface{})
@@ -773,15 +774,18 @@ func PutIntConst(ctxt Context, info, typ Sym, name string, val int64) {
 // attribute).
 func PutRanges(ctxt Context, sym Sym, base Sym, ranges []Range) {
        ps := ctxt.PtrSize()
-       // Write base address entry.
-       if base != nil {
-               ctxt.AddInt(sym, ps, -1)
-               ctxt.AddAddress(sym, base, 0)
-       }
        // 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 {
-               ctxt.AddInt(sym, ps, r.Start)
-               ctxt.AddInt(sym, ps, r.End)
+               if base == nil {
+                       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.
        ctxt.AddInt(sym, ps, 0)
index 23d1809e0c146386a44341a7d0a2d9d0dd0a1831..ce0dd09a4f0939ca4a74bc3c0e01e8cb2077038b 100644 (file)
@@ -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.
-// rsym and roff specify the relocation for the address.
-func (s *LSym) WriteAddr(ctxt *Link, off int64, siz int, rsym *LSym, roff int64) {
+func (s *LSym) writeAddr(ctxt *Link, off int64, siz int, rsym *LSym, roff int64, rtype objabi.RelocType) {
        // Allow 4-byte addresses for DWARF.
        if siz != ctxt.Arch.PtrSize && siz != 4 {
                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)
        }
        r.Siz = uint8(siz)
        r.Sym = rsym
-       r.Type = objabi.R_ADDR
+       r.Type = rtype
        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.
 // After linking the 4 bytes stored at s+off will be
 // rsym+roff-(start of section that s is in).
index 7098d203dd3c4a63bd630b4729bf53a036c7d3df..9372fb34da9e014231f8e734f485bb694286c672 100644 (file)
@@ -453,6 +453,11 @@ func (c dwCtxt) AddAddress(s dwarf.Sym, data interface{}, value int64) {
                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) {
        ls := s.(*LSym)
        rsym := t.(*LSym)
index 82e3161cf4aa895ddbb8556dc981df11342a91ca..2e0b916f7c1a896c24927dc17b2afdb5dfef2039 100644 (file)
@@ -190,6 +190,9 @@ const (
        // 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.
        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.
index 792d6314860664bcade81f988d80730d1d006f95..a6efe9cad046767869382de4611212b994ee8955 100644 (file)
@@ -4,9 +4,9 @@ package objabi
 
 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 {
        i -= 1
index d3884f3515ecee01ea1cb6df169d09ab0804e07b..79b9ae1013703ce7226c84f0c3ce86ff52f2acf4 100644 (file)
@@ -367,6 +367,11 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
                                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.
                case objabi.R_GOTPCREL:
                        if ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin && r.Sym != nil && r.Sym.Type != sym.SCONST {
index 600c49aa129025c77f8945254fdc2b20086a929e..c5c48e5c854c737150c22392c3c7600ea3ebe208 100644 (file)
@@ -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).
        textp := make([]*sym.Symbol, 0, len(ctxt.Textp))
        for _, s := range ctxt.Textp {
                if s.Attr.Reachable() {
+                       if s.Lib != nil {
+                               s.Lib.Textp = append(s.Lib.Textp, s)
+                       }
                        textp = append(textp, s)
                }
        }
index d0fae2c79faa2c385d3c48afbcb74f614a5b4da6..03facbcd58f23951c348bb9ae511802c2e325b63 100644 (file)
@@ -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)
 }
 
+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) {
        ls := s.(*sym.Symbol)
        switch size {
@@ -843,7 +850,6 @@ func defdwsymb(ctxt *Link, s *sym.Symbol, str string, t SymbolType, v int64, got
 // debug-related data.
 type compilationUnit struct {
        lib      *sym.Library
-       textp    []*sym.Symbol // Function symbols in this package
        consts   *sym.Symbol   // Package constants DIEs
        pcs      []dwarf.Range // PC ranges, relative to textp[0]
        dwinfo   *dwarf.DWDie  // CU root DIE
@@ -869,7 +875,6 @@ func getCompilationUnits(ctxt *Link) []*compilationUnit {
                        units = append(units, unit)
                        index[s.Lib] = unit
                }
-               unit.textp = append(unit.textp, s)
 
                // Update PC ranges.
                //
@@ -879,10 +884,10 @@ func getCompilationUnits(ctxt *Link) []*compilationUnit {
                // only create boundaries between symbols from
                // different units.
                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
                }
-               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
 }
@@ -1612,8 +1617,8 @@ func dwarfgeneratedebugsyms(ctxt *Link) {
        debugRanges.Attr |= sym.AttrReachable
        syms = append(syms, debugLine)
        for _, u := range units {
-               u.dwinfo, u.funcDIEs = writelines(ctxt, u.lib, u.textp, debugLine)
-               writepcranges(ctxt, u.dwinfo, u.textp[0], u.pcs, debugRanges)
+               u.dwinfo, u.funcDIEs = writelines(ctxt, u.lib, u.lib.Textp, debugLine)
+               writepcranges(ctxt, u.dwinfo, u.lib.Textp[0], u.pcs, debugRanges)
        }
 
        synthesizestringtypes(ctxt, dwtypes.Child)
index b3ff6c4e19079dc8fc658f5486d70623312eef6b..6faedf4fe277748da60d7b5ff2083ae38a9d4d3b 100644 (file)
@@ -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))
 }
 
-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 {
                s.Type = SDATA
        }
@@ -145,11 +145,19 @@ func (s *Symbol) AddAddrPlus(arch *sys.Arch, t *Symbol, add int64) int64 {
        r.Sym = t
        r.Off = int32(i)
        r.Siz = uint8(arch.PtrSize)
-       r.Type = objabi.R_ADDR
+       r.Type = typ
        r.Add = add
        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 {
        if s.Type == 0 {
                s.Type = SDATA