Commit f00bfb38 authored by Than McIntosh's avatar Than McIntosh Committed by Brad Fitzpatrick

cmd/link: split off 'Dynimp' string fields to reduce sym.Symbol size

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/121916Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
parent 32bc0976
...@@ -1030,8 +1030,8 @@ func elfdynhash(ctxt *Link) { ...@@ -1030,8 +1030,8 @@ func elfdynhash(ctxt *Link) {
continue continue
} }
if sy.Dynimpvers != "" { if sy.Dynimpvers() != "" {
need[sy.Dynid] = addelflib(&needlib, sy.Dynimplib, sy.Dynimpvers) need[sy.Dynid] = addelflib(&needlib, sy.Dynimplib(), sy.Dynimpvers())
} }
name := sy.Extname name := sy.Extname
...@@ -2287,8 +2287,8 @@ func elfadddynsym(ctxt *Link, s *sym.Symbol) { ...@@ -2287,8 +2287,8 @@ func elfadddynsym(ctxt *Link, s *sym.Symbol) {
/* size of object */ /* size of object */
d.AddUint64(ctxt.Arch, uint64(s.Size)) d.AddUint64(ctxt.Arch, uint64(s.Size))
if ctxt.Arch.Family == sys.AMD64 && !s.Attr.CgoExportDynamic() && s.Dynimplib != "" && !seenlib[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))) Elfwritedynent(ctxt, ctxt.Syms.Lookup(".dynamic", 0), DT_NEEDED, uint64(Addstring(ctxt.Syms.Lookup(".dynstr", 0), s.Dynimplib())))
} }
} else { } else {
s.Dynid = int32(Nelfsym) s.Dynid = int32(Nelfsym)
......
...@@ -155,9 +155,9 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) { ...@@ -155,9 +155,9 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
} }
s := ctxt.Syms.Lookup(local, 0) s := ctxt.Syms.Lookup(local, 0)
if s.Type == 0 || s.Type == sym.SXREF || s.Type == sym.SHOSTOBJ { if s.Type == 0 || s.Type == sym.SXREF || s.Type == sym.SHOSTOBJ {
s.Dynimplib = lib s.SetDynimplib(lib)
s.Extname = remote s.Extname = remote
s.Dynimpvers = q s.SetDynimpvers(q)
if s.Type != sym.SHOSTOBJ { if s.Type != sym.SHOSTOBJ {
s.Type = sym.SDYNIMPORT s.Type = sym.SDYNIMPORT
} }
...@@ -198,10 +198,9 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) { ...@@ -198,10 +198,9 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
// export overrides import, for openbsd/cgo. // export overrides import, for openbsd/cgo.
// see issue 4878. // see issue 4878.
if s.Dynimplib != "" { if s.Dynimplib() != "" {
s.Dynimplib = "" s.ResetDyninfo()
s.Extname = "" s.Extname = ""
s.Dynimpvers = ""
s.Type = 0 s.Type = 0
} }
......
...@@ -416,7 +416,7 @@ func (ctxt *Link) loadlib() { ...@@ -416,7 +416,7 @@ func (ctxt *Link) loadlib() {
// cgo_import_static and cgo_import_dynamic, // cgo_import_static and cgo_import_dynamic,
// then we want to make it cgo_import_dynamic // then we want to make it cgo_import_dynamic
// now. // now.
if s.Extname != "" && s.Dynimplib != "" && !s.Attr.CgoExport() { if s.Extname != "" && s.Dynimplib() != "" && !s.Attr.CgoExport() {
s.Type = sym.SDYNIMPORT s.Type = sym.SDYNIMPORT
} else { } else {
s.Type = 0 s.Type = 0
......
...@@ -989,7 +989,7 @@ func initdynimport(ctxt *Link) *Dll { ...@@ -989,7 +989,7 @@ func initdynimport(ctxt *Link) *Dll {
continue continue
} }
for d = dr; d != nil; d = d.next { for d = dr; d != nil; d = d.next {
if d.name == s.Dynimplib { if d.name == s.Dynimplib() {
m = new(Imp) m = new(Imp)
break break
} }
...@@ -997,7 +997,7 @@ func initdynimport(ctxt *Link) *Dll { ...@@ -997,7 +997,7 @@ func initdynimport(ctxt *Link) *Dll {
if d == nil { if d == nil {
d = new(Dll) d = new(Dll)
d.name = s.Dynimplib d.name = s.Dynimplib()
d.next = dr d.next = dr
dr = d dr = d
m = new(Imp) m = new(Imp)
......
...@@ -805,7 +805,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length i ...@@ -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.Type = sect.sym.Type
s.Attr |= sym.AttrSubSymbol s.Attr |= sym.AttrSubSymbol
if !s.Attr.CgoExportDynamic() { if !s.Attr.CgoExportDynamic() {
s.Dynimplib = "" // satisfy dynimport s.SetDynimplib("") // satisfy dynimport
} }
s.Value = int64(elfsym.value) s.Value = int64(elfsym.value)
s.Size = int64(elfsym.size) s.Size = int64(elfsym.size)
......
...@@ -644,7 +644,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length i ...@@ -644,7 +644,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length i
s.Outer = outer s.Outer = outer
s.Value = int64(machsym.value - sect.addr) s.Value = int64(machsym.value - sect.addr)
if !s.Attr.CgoExportDynamic() { if !s.Attr.CgoExportDynamic() {
s.Dynimplib = "" // satisfy dynimport s.SetDynimplib("") // satisfy dynimport
} }
if outer.Type == sym.STEXT { if outer.Type == sym.STEXT {
if s.Attr.External() && !s.Attr.DuplicateOK() { if s.Attr.External() && !s.Attr.DuplicateOK() {
......
...@@ -31,21 +31,25 @@ type Symbol struct { ...@@ -31,21 +31,25 @@ type Symbol struct {
// ElfType is set for symbols read from shared libraries by ldshlibsyms. It // 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 // 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). // read by ldelf (and so is left as elf.STT_NOTYPE).
ElfType elf.SymType ElfType elf.SymType
Sub *Symbol Sub *Symbol
Outer *Symbol Outer *Symbol
Gotype *Symbol Gotype *Symbol
File string File string
Dynimplib string dyninfo *dynimp
Dynimpvers string Sect *Section
Sect *Section FuncInfo *FuncInfo
FuncInfo *FuncInfo Lib *Library // Package defining this symbol
Lib *Library // Package defining this symbol
// P contains the raw symbol data. // P contains the raw symbol data.
P []byte P []byte
R []Reloc R []Reloc
} }
type dynimp struct {
dynimplib string
dynimpvers string
}
func (s *Symbol) String() string { func (s *Symbol) String() string {
if s.Version == 0 { if s.Version == 0 {
return s.Name return s.Name
...@@ -264,6 +268,40 @@ func (s *Symbol) setUintXX(arch *sys.Arch, off int64, v uint64, wid int64) int64 ...@@ -264,6 +268,40 @@ func (s *Symbol) setUintXX(arch *sys.Arch, off int64, v uint64, wid int64) int64
return off + wid 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. // SortSub sorts a linked-list (by Sub) of *Symbol by Value.
// Used for sub-symbols when loading host objects (see e.g. ldelf.go). // Used for sub-symbols when loading host objects (see e.g. ldelf.go).
func SortSub(l *Symbol) *Symbol { func SortSub(l *Symbol) *Symbol {
......
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