From 4ad94a5db983da3487108dbeed26e75e5c72a2c6 Mon Sep 17 00:00:00 2001 From: Jeremy Faller Date: Wed, 22 Jan 2020 15:24:39 -0500 Subject: [PATCH] [dev.link] cmd/link: use new sym builders in macho loader Change-Id: Ia055559d1eb12736d0bdd5a30103cd4b9788d36e Reviewed-on: https://go-review.googlesource.com/c/go/+/215917 Run-TryBot: Jeremy Faller TryBot-Result: Gobot Gobot Reviewed-by: Cherry Zhang --- src/cmd/link/internal/ld/lib.go | 5 +- src/cmd/link/internal/loader/loader.go | 7 +- src/cmd/link/internal/loader/symbolbuilder.go | 49 +++++-- src/cmd/link/internal/loadmacho/ldmacho.go | 128 +++++++++--------- 4 files changed, 111 insertions(+), 78 deletions(-) diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 3e79b92d75..c1b56276b0 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -457,7 +457,8 @@ func (ctxt *Link) loadlib() { } // Process cgo directives (has to be done before host object loading). - ctxt.loadcgodirectives(ctxt.IsELF && *FlagNewLdElf) + newCgo := (ctxt.IsELF && *FlagNewLdElf) || ctxt.HeadType == objabi.Hdarwin + ctxt.loadcgodirectives(newCgo) // Conditionally load host objects, or setup for external linking. hostobjs(ctxt) @@ -1888,7 +1889,7 @@ func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string, Errorf(nil, "%v", err) return } - ctxt.Textp = append(ctxt.Textp, textp...) + ctxt.Textp2 = append(ctxt.Textp2, textp...) } return ldhostobj(ldmacho, ctxt.HeadType, f, pkg, length, pn, file) } diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index f7bbd7a38f..47393a9584 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -674,6 +674,9 @@ func (l *Loader) NDef() int { // Returns the raw (unpatched) name of the i-th symbol. func (l *Loader) RawSymName(i Sym) string { + if ov, ok := l.overwrite[i]; ok { + i = ov + } if l.IsExternal(i) { if s := l.Syms[i]; s != nil { return s.Name @@ -904,7 +907,7 @@ func (l *Loader) AttrExternal(i Sym) bool { // symbol (see AttrExternal). func (l *Loader) SetAttrExternal(i Sym, v bool) { if i < l.extStart { - panic("tried to set external attr on non-external symbol") + panic(fmt.Sprintf("tried to set external attr on non-external symbol %q", l.RawSymName(i))) } if v { l.attrExternal.set(i - l.extStart) @@ -2110,6 +2113,7 @@ func (l *Loader) copyAttributes(src Sym, dst Sym) { l.SetAttrSpecial(dst, l.AttrSpecial(src)) l.SetAttrCgoExportDynamic(dst, l.AttrCgoExportDynamic(src)) l.SetAttrCgoExportStatic(dst, l.AttrCgoExportStatic(src)) + l.SetAttrReadOnly(dst, l.AttrReadOnly(src)) } // migrateAttributes copies over all of the attributes of symbol 'src' to @@ -2128,6 +2132,7 @@ func (l *Loader) migrateAttributes(src Sym, dst *sym.Symbol) { dst.Attr.Set(sym.AttrSpecial, l.AttrSpecial(src)) dst.Attr.Set(sym.AttrCgoExportDynamic, l.AttrCgoExportDynamic(src)) dst.Attr.Set(sym.AttrCgoExportStatic, l.AttrCgoExportStatic(src)) + dst.Attr.Set(sym.AttrReadOnly, l.AttrReadOnly(src)) // Convert outer/sub relationships if outer, ok := l.outer[src]; ok { diff --git a/src/cmd/link/internal/loader/symbolbuilder.go b/src/cmd/link/internal/loader/symbolbuilder.go index a815a69617..20646349c7 100644 --- a/src/cmd/link/internal/loader/symbolbuilder.go +++ b/src/cmd/link/internal/loader/symbolbuilder.go @@ -8,6 +8,7 @@ import ( "cmd/internal/objabi" "cmd/internal/sys" "cmd/link/internal/sym" + "fmt" ) // SymbolBuilder is a helper designed to help with the construction @@ -47,7 +48,7 @@ func (l *Loader) MakeSymbolUpdater(symIdx Sym) (*SymbolBuilder, Sym) { symIdx = l.cloneToExternal(symIdx) } if l.Syms[symIdx] != nil { - panic("can't build if sym.Symbol already present") + panic(fmt.Sprintf("can't build if sym.Symbol %q already present", l.RawSymName(symIdx))) } // Construct updater and return. @@ -58,24 +59,30 @@ func (l *Loader) MakeSymbolUpdater(symIdx Sym) (*SymbolBuilder, Sym) { // Getters for properties of the symbol we're working on. -func (sb *SymbolBuilder) Sym() Sym { return sb.symIdx } -func (sb *SymbolBuilder) Name() string { return sb.name } -func (sb *SymbolBuilder) Version() int { return sb.ver } -func (sb *SymbolBuilder) Type() sym.SymKind { return sb.kind } -func (sb *SymbolBuilder) Size() int64 { return sb.size } -func (sb *SymbolBuilder) Data() []byte { return sb.data } -func (sb *SymbolBuilder) Value() int64 { return sb.l.SymValue(sb.symIdx) } -func (sb *SymbolBuilder) Align() int32 { return sb.l.SymAlign(sb.symIdx) } -func (sb *SymbolBuilder) Localentry() uint8 { return sb.l.SymLocalentry(sb.symIdx) } -func (sb *SymbolBuilder) Extname() string { return sb.l.SymExtname(sb.symIdx) } -func (sb *SymbolBuilder) Dynimplib() string { return sb.l.SymDynimplib(sb.symIdx) } -func (sb *SymbolBuilder) Dynimpvers() string { return sb.l.SymDynimpvers(sb.symIdx) } +func (sb *SymbolBuilder) Sym() Sym { return sb.symIdx } +func (sb *SymbolBuilder) Name() string { return sb.name } +func (sb *SymbolBuilder) Version() int { return sb.ver } +func (sb *SymbolBuilder) Type() sym.SymKind { return sb.kind } +func (sb *SymbolBuilder) Size() int64 { return sb.size } +func (sb *SymbolBuilder) Data() []byte { return sb.data } +func (sb *SymbolBuilder) Value() int64 { return sb.l.SymValue(sb.symIdx) } +func (sb *SymbolBuilder) Align() int32 { return sb.l.SymAlign(sb.symIdx) } +func (sb *SymbolBuilder) Localentry() uint8 { return sb.l.SymLocalentry(sb.symIdx) } +func (sb *SymbolBuilder) OnList() bool { return sb.l.AttrOnList(sb.symIdx) } +func (sb *SymbolBuilder) External() bool { return sb.l.AttrExternal(sb.symIdx) } +func (sb *SymbolBuilder) Extname() string { return sb.l.SymExtname(sb.symIdx) } +func (sb *SymbolBuilder) CgoExportDynamic() bool { return sb.l.AttrCgoExportDynamic(sb.symIdx) } +func (sb *SymbolBuilder) Dynimplib() string { return sb.l.SymDynimplib(sb.symIdx) } +func (sb *SymbolBuilder) Dynimpvers() string { return sb.l.SymDynimpvers(sb.symIdx) } +func (sb *SymbolBuilder) SubSym() Sym { return sb.l.SubSym(sb.symIdx) } // Setters for symbol properties. func (sb *SymbolBuilder) SetType(kind sym.SymKind) { sb.kind = kind } func (sb *SymbolBuilder) SetSize(size int64) { sb.size = size } func (sb *SymbolBuilder) SetData(data []byte) { sb.data = data } +func (sb *SymbolBuilder) SetOnList(v bool) { sb.l.SetAttrOnList(sb.symIdx, v) } +func (sb *SymbolBuilder) SetExternal(v bool) { sb.l.SetAttrExternal(sb.symIdx, v) } func (sb *SymbolBuilder) SetValue(v int64) { sb.l.SetSymValue(sb.symIdx, v) } func (sb *SymbolBuilder) SetAlign(align int32) { sb.l.SetSymAlign(sb.symIdx, align) } func (sb *SymbolBuilder) SetLocalentry(value uint8) { sb.l.SetSymLocalentry(sb.symIdx, value) } @@ -112,6 +119,22 @@ func (sb *SymbolBuilder) setReachable() { sb.l.SetAttrReachable(sb.symIdx, true) } +func (sb *SymbolBuilder) ReadOnly() bool { + return sb.l.AttrReadOnly(sb.symIdx) +} + +func (sb *SymbolBuilder) SetReadOnly(v bool) { + sb.l.SetAttrReadOnly(sb.symIdx, v) +} + +func (sb *SymbolBuilder) DuplicateOK() bool { + return sb.l.AttrDuplicateOK(sb.symIdx) +} + +func (sb *SymbolBuilder) SetDuplicateOK(v bool) { + sb.l.SetAttrDuplicateOK(sb.symIdx, v) +} + func (sb *SymbolBuilder) Outer() Sym { return sb.l.OuterSym(sb.symIdx) } diff --git a/src/cmd/link/internal/loadmacho/ldmacho.go b/src/cmd/link/internal/loadmacho/ldmacho.go index e27701403e..6e74e0a076 100644 --- a/src/cmd/link/internal/loadmacho/ldmacho.go +++ b/src/cmd/link/internal/loadmacho/ldmacho.go @@ -100,7 +100,7 @@ type ldMachoSect struct { flags uint32 res1 uint32 res2 uint32 - sym *sym.Symbol + sym loader.Sym rel []ldMachoRel } @@ -131,7 +131,7 @@ type ldMachoSym struct { desc uint16 kind int8 value uint64 - sym *sym.Symbol + sym loader.Sym } type ldMachoDysymtab struct { @@ -423,8 +423,8 @@ func macholoadsym(m *ldMachoObj, symtab *ldMachoSymtab) int { // Load the Mach-O file pn from f. // Symbols are written into syms, and a slice of the text symbols is returned. -func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader, pkg string, length int64, pn string) (textp []*sym.Symbol, err error) { - errorf := func(str string, args ...interface{}) ([]*sym.Symbol, error) { +func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader, pkg string, length int64, pn string) (textp []loader.Sym, err error) { + errorf := func(str string, args ...interface{}) ([]loader.Sym, error) { return nil, fmt.Errorf("loadmacho: %v: %v", pn, fmt.Sprintf(str, args...)) } @@ -559,31 +559,31 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader, continue } name := fmt.Sprintf("%s(%s/%s)", pkg, sect.segname, sect.name) - s := l.LookupOrCreate(name, localSymVersion) - if s.Type != 0 { + bld, s := l.MakeSymbolUpdater(l.LookupOrCreateSym(name, localSymVersion)) + if bld.Type() != 0 { return errorf("duplicate %s/%s", sect.segname, sect.name) } if sect.flags&0xff == 1 { // S_ZEROFILL - s.P = make([]byte, sect.size) + bld.SetData(make([]byte, sect.size)) } else { - s.Attr.Set(sym.AttrReadOnly, readOnly) - s.P = dat[sect.addr-c.seg.vmaddr:][:sect.size] + bld.SetReadOnly(readOnly) + bld.SetData(dat[sect.addr-c.seg.vmaddr:][:sect.size]) } - s.Size = int64(len(s.P)) + bld.SetSize(int64(len(bld.Data()))) if sect.segname == "__TEXT" { if sect.name == "__text" { - s.Type = sym.STEXT + bld.SetType(sym.STEXT) } else { - s.Type = sym.SRODATA + bld.SetType(sym.SRODATA) } } else { if sect.name == "__bss" { - s.Type = sym.SNOPTRBSS - s.P = s.P[:0] + bld.SetType(sym.SNOPTRBSS) + bld.SetData(nil) } else { - s.Type = sym.SNOPTRDATA + bld.SetType(sym.SNOPTRDATA) } } @@ -608,12 +608,12 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader, if machsym.type_&N_EXT == 0 { v = localSymVersion } - s := l.LookupOrCreate(name, v) + s := l.LookupOrCreateSym(name, v) if machsym.type_&N_EXT == 0 { - s.Attr |= sym.AttrDuplicateOK + l.SetAttrDuplicateOK(s, true) } if machsym.desc&(N_WEAK_REF|N_WEAK_DEF) != 0 { - s.Attr |= sym.AttrDuplicateOK + l.SetAttrDuplicateOK(s, true) } machsym.sym = s if machsym.sectnum == 0 { // undefined @@ -624,69 +624,72 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader, } sect := &c.seg.sect[machsym.sectnum-1] + bld, bldSym := l.MakeSymbolUpdater(s) outer := sect.sym - if outer == nil { + if outer == 0 { continue // ignore reference to invalid section } - if s.Outer != nil { - if s.Attr.DuplicateOK() { + if osym := l.OuterSym(s); osym != 0 { + if l.AttrDuplicateOK(s) { continue } - return errorf("duplicate symbol reference: %s in both %s and %s", s.Name, s.Outer.Name, sect.sym.Name) + return errorf("duplicate symbol reference: %s in both %s and %s", l.SymName(s), l.SymName(osym), l.SymName(sect.sym)) } - s.Type = outer.Type - s.Attr |= sym.AttrSubSymbol - s.Sub = outer.Sub - outer.Sub = s - s.Outer = outer - s.Value = int64(machsym.value - sect.addr) - if !s.Attr.CgoExportDynamic() { - s.SetDynimplib("") // satisfy dynimport + bld.SetType(l.SymType(outer)) + l.PrependSub(outer, bldSym) + + bld.SetValue(int64(machsym.value - sect.addr)) + if !l.AttrCgoExportDynamic(s) { + bld.SetDynimplib("") // satisfy dynimport } - if outer.Type == sym.STEXT { - if s.Attr.External() && !s.Attr.DuplicateOK() { + if l.SymType(outer) == sym.STEXT { + if bld.External() && !bld.DuplicateOK() { return errorf("%v: duplicate symbol definition", s) } - s.Attr |= sym.AttrExternal + bld.SetExternal(true) } - machsym.sym = s + machsym.sym = bldSym } // Sort outer lists by address, adding to textp. // This keeps textp in increasing address order. for i := 0; uint32(i) < c.seg.nsect; i++ { sect := &c.seg.sect[i] - s := sect.sym - if s == nil { + sectSym := sect.sym + if sectSym == 0 { continue } - if s.Sub != nil { - s.Sub = sym.SortSub(s.Sub) + bld, s := l.MakeSymbolUpdater(sectSym) + if bld.SubSym() != 0 { + + bld.SortSub() // assign sizes, now that we know symbols in sorted order. - for s1 := s.Sub; s1 != nil; s1 = s1.Sub { - if s1.Sub != nil { - s1.Size = s1.Sub.Value - s1.Value + for s1 := bld.Sub(); s1 != 0; s1 = l.SubSym(s1) { + s1Bld, _ := l.MakeSymbolUpdater(s1) + if sub := l.SubSym(s1); sub != 0 { + s1Bld.SetSize(l.SymValue(sub) - l.SymValue(s1)) } else { - s1.Size = s.Value + s.Size - s1.Value + dlen := int64(len(l.Data(s))) + s1Bld.SetSize(l.SymValue(s) + dlen - l.SymValue(s1)) } } } - if s.Type == sym.STEXT { - if s.Attr.OnList() { - return errorf("symbol %s listed multiple times", s.Name) + if bld.Type() == sym.STEXT { + if bld.OnList() { + return errorf("symbol %s listed multiple times", bld.Name()) } - s.Attr |= sym.AttrOnList + bld.SetOnList(true) textp = append(textp, s) - for s1 := s.Sub; s1 != nil; s1 = s1.Sub { - if s1.Attr.OnList() { - return errorf("symbol %s listed multiple times", s1.Name) + for s1 := bld.Sub(); s1 != 0; s1 = l.SubSym(s1) { + if l.AttrOnList(s1) { + return errorf("symbol %s listed multiple times", l.RawSymName(s1)) } - s1.Attr |= sym.AttrOnList + l.SetAttrOnList(s1, true) textp = append(textp, s1) } } @@ -696,14 +699,14 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader, for i := 0; uint32(i) < c.seg.nsect; i++ { sect := &c.seg.sect[i] s := sect.sym - if s == nil { + if s == 0 { continue } macholoadrel(m, sect) if sect.rel == nil { continue } - r := make([]sym.Reloc, sect.nreloc) + r := make([]loader.Reloc, sect.nreloc) rpi := 0 Reloc: for j := uint32(0); j < sect.nreloc; j++ { @@ -728,7 +731,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader, return errorf("unsupported scattered relocation %d/%d", int(rel.type_), int(sect.rel[j+1].type_)) } - rp.Siz = rel.length + rp.Size = rel.length rp.Off = int32(rel.addr) // NOTE(rsc): I haven't worked out why (really when) @@ -752,7 +755,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader, for k := 0; uint32(k) < c.seg.nsect; k++ { ks := &c.seg.sect[k] if ks.addr <= uint64(rel.value) && uint64(rel.value) < ks.addr+ks.size { - if ks.sym != nil { + if ks.sym != 0 { rp.Sym = ks.sym rp.Add += int64(uint64(rel.value) - ks.addr) } else if ks.segname == "__IMPORT" && ks.name == "__pointers" { @@ -792,11 +795,12 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader, return errorf("unsupported scattered relocation: invalid address %#x", rel.addr) } - rp.Siz = rel.length + rp.Size = rel.length rp.Type = objabi.MachoRelocOffset + (objabi.RelocType(rel.type_) << 1) + objabi.RelocType(rel.pcrel) rp.Off = int32(rel.addr) // Handle X86_64_RELOC_SIGNED referencing a section (rel->extrn == 0). + p := l.Data(s) if arch.Family == sys.AMD64 && rel.extrn == 0 && rel.type_ == MACHO_X86_64_RELOC_SIGNED { // Calculate the addend as the offset into the section. // @@ -815,9 +819,9 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader, // [For future reference, see Darwin's /usr/include/mach-o/x86_64/reloc.h] secaddr := c.seg.sect[rel.symnum-1].addr - rp.Add = int64(uint64(int64(int32(e.Uint32(s.P[rp.Off:])))+int64(rp.Off)+4) - secaddr) + rp.Add = int64(uint64(int64(int32(e.Uint32(p[rp.Off:])))+int64(rp.Off)+4) - secaddr) } else { - rp.Add = int64(int32(e.Uint32(s.P[rp.Off:]))) + rp.Add = int64(int32(e.Uint32(p[rp.Off:]))) } // An unsigned internal relocation has a value offset @@ -831,7 +835,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader, // it *is* the PC being subtracted. Use that to make // it match our version of PC-relative. if rel.pcrel != 0 && arch.Family == sys.I386 { - rp.Add += int64(rp.Off) + int64(rp.Siz) + rp.Add += int64(rp.Off) + int64(rp.Size) } if rel.extrn == 0 { if rel.symnum < 1 || rel.symnum > c.seg.nsect { @@ -839,7 +843,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader, } rp.Sym = c.seg.sect[rel.symnum-1].sym - if rp.Sym == nil { + if rp.Sym == 0 { return errorf("invalid relocation: %s", c.seg.sect[rel.symnum-1].name) } @@ -861,9 +865,9 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader, rpi++ } - sort.Sort(sym.RelocByOff(r[:rpi])) - s.R = r - s.R = s.R[:rpi] + sort.Sort(loader.RelocByOff(r[:rpi])) + sb, _ := l.MakeSymbolUpdater(sect.sym) + sb.SetRelocs(r[:rpi]) } return textp, nil -- 2.48.1