Skip to content

Commit

Permalink
cmd/link: split off 'Dynimp' string fields to reduce sym.Symbol size
Browse files Browse the repository at this point in the history
The linker's sym.Symbol struct contains two string fields, "Dynimplib"
and "Dynimpvers" that are used only in very specific circumstances
(for many symbols, such as DWARF syms, they are wasted space). Split
these two off into a separate struct, then point to an instance of
that struct when needed. This reduces the size of sym.Symbol so as to
save space in the common case.

Updates #26186

Change-Id: Id9c74824e78423a215c8cbc105b72665525a1eff
Reviewed-on: https://go-review.googlesource.com/121916
Reviewed-by: Ian Lance Taylor <[email protected]>
  • Loading branch information
thanm committed Jul 3, 2018
1 parent 1986798 commit d592ac1
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 24 deletions.
8 changes: 4 additions & 4 deletions src/cmd/link/internal/ld/elf.go
Original file line number Diff line number Diff line change
Expand Up @@ -1030,8 +1030,8 @@ func elfdynhash(ctxt *Link) {
continue
}

if sy.Dynimpvers != "" {
need[sy.Dynid] = addelflib(&needlib, sy.Dynimplib, sy.Dynimpvers)
if sy.Dynimpvers() != "" {
need[sy.Dynid] = addelflib(&needlib, sy.Dynimplib(), sy.Dynimpvers())
}

name := sy.Extname
Expand Down Expand Up @@ -2287,8 +2287,8 @@ func elfadddynsym(ctxt *Link, s *sym.Symbol) {
/* size of object */
d.AddUint64(ctxt.Arch, uint64(s.Size))

if ctxt.Arch.Family == sys.AMD64 && !s.Attr.CgoExportDynamic() && s.Dynimplib != "" && !seenlib[s.Dynimplib] {
Elfwritedynent(ctxt, ctxt.Syms.Lookup(".dynamic", 0), DT_NEEDED, uint64(Addstring(ctxt.Syms.Lookup(".dynstr", 0), s.Dynimplib)))
if ctxt.Arch.Family == sys.AMD64 && !s.Attr.CgoExportDynamic() && s.Dynimplib() != "" && !seenlib[s.Dynimplib()] {
Elfwritedynent(ctxt, ctxt.Syms.Lookup(".dynamic", 0), DT_NEEDED, uint64(Addstring(ctxt.Syms.Lookup(".dynstr", 0), s.Dynimplib())))
}
} else {
s.Dynid = int32(Nelfsym)
Expand Down
9 changes: 4 additions & 5 deletions src/cmd/link/internal/ld/go.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,9 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
}
s := ctxt.Syms.Lookup(local, 0)
if s.Type == 0 || s.Type == sym.SXREF || s.Type == sym.SHOSTOBJ {
s.Dynimplib = lib
s.SetDynimplib(lib)
s.Extname = remote
s.Dynimpvers = q
s.SetDynimpvers(q)
if s.Type != sym.SHOSTOBJ {
s.Type = sym.SDYNIMPORT
}
Expand Down Expand Up @@ -198,10 +198,9 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {

// export overrides import, for openbsd/cgo.
// see issue 4878.
if s.Dynimplib != "" {
s.Dynimplib = ""
if s.Dynimplib() != "" {
s.ResetDyninfo()
s.Extname = ""
s.Dynimpvers = ""
s.Type = 0
}

Expand Down
2 changes: 1 addition & 1 deletion src/cmd/link/internal/ld/lib.go
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ func (ctxt *Link) loadlib() {
// cgo_import_static and cgo_import_dynamic,
// then we want to make it cgo_import_dynamic
// now.
if s.Extname != "" && s.Dynimplib != "" && !s.Attr.CgoExport() {
if s.Extname != "" && s.Dynimplib() != "" && !s.Attr.CgoExport() {
s.Type = sym.SDYNIMPORT
} else {
s.Type = 0
Expand Down
4 changes: 2 additions & 2 deletions src/cmd/link/internal/ld/pe.go
Original file line number Diff line number Diff line change
Expand Up @@ -989,15 +989,15 @@ func initdynimport(ctxt *Link) *Dll {
continue
}
for d = dr; d != nil; d = d.next {
if d.name == s.Dynimplib {
if d.name == s.Dynimplib() {
m = new(Imp)
break
}
}

if d == nil {
d = new(Dll)
d.name = s.Dynimplib
d.name = s.Dynimplib()
d.next = dr
dr = d
m = new(Imp)
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/link/internal/loadelf/ldelf.go
Original file line number Diff line number Diff line change
Expand Up @@ -805,7 +805,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length i
s.Type = sect.sym.Type
s.Attr |= sym.AttrSubSymbol
if !s.Attr.CgoExportDynamic() {
s.Dynimplib = "" // satisfy dynimport
s.SetDynimplib("") // satisfy dynimport
}
s.Value = int64(elfsym.value)
s.Size = int64(elfsym.size)
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/link/internal/loadmacho/ldmacho.go
Original file line number Diff line number Diff line change
Expand Up @@ -644,7 +644,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length i
s.Outer = outer
s.Value = int64(machsym.value - sect.addr)
if !s.Attr.CgoExportDynamic() {
s.Dynimplib = "" // satisfy dynimport
s.SetDynimplib("") // satisfy dynimport
}
if outer.Type == sym.STEXT {
if s.Attr.External() && !s.Attr.DuplicateOK() {
Expand Down
58 changes: 48 additions & 10 deletions src/cmd/link/internal/sym/symbol.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,25 @@ type Symbol struct {
// ElfType is set for symbols read from shared libraries by ldshlibsyms. It
// is not set for symbols defined by the packages being linked or by symbols
// read by ldelf (and so is left as elf.STT_NOTYPE).
ElfType elf.SymType
Sub *Symbol
Outer *Symbol
Gotype *Symbol
File string
Dynimplib string
Dynimpvers string
Sect *Section
FuncInfo *FuncInfo
Lib *Library // Package defining this symbol
ElfType elf.SymType
Sub *Symbol
Outer *Symbol
Gotype *Symbol
File string
dyninfo *dynimp
Sect *Section
FuncInfo *FuncInfo
Lib *Library // Package defining this symbol
// P contains the raw symbol data.
P []byte
R []Reloc
}

type dynimp struct {
dynimplib string
dynimpvers string
}

func (s *Symbol) String() string {
if s.Version == 0 {
return s.Name
Expand Down Expand Up @@ -264,6 +268,40 @@ func (s *Symbol) setUintXX(arch *sys.Arch, off int64, v uint64, wid int64) int64
return off + wid
}

func (s *Symbol) Dynimplib() string {
if s.dyninfo == nil {
return ""
}
return s.dyninfo.dynimplib
}

func (s *Symbol) Dynimpvers() string {
if s.dyninfo == nil {
return ""
}
return s.dyninfo.dynimpvers
}

func (s *Symbol) SetDynimplib(lib string) {
if s.dyninfo == nil {
s.dyninfo = &dynimp{dynimplib: lib}
} else {
s.dyninfo.dynimplib = lib
}
}

func (s *Symbol) SetDynimpvers(vers string) {
if s.dyninfo == nil {
s.dyninfo = &dynimp{dynimpvers: vers}
} else {
s.dyninfo.dynimpvers = vers
}
}

func (s *Symbol) ResetDyninfo() {
s.dyninfo = nil
}

// SortSub sorts a linked-list (by Sub) of *Symbol by Value.
// Used for sub-symbols when loading host objects (see e.g. ldelf.go).
func SortSub(l *Symbol) *Symbol {
Expand Down

0 comments on commit d592ac1

Please sign in to comment.